.tmp.
							parent
							
								
									5754f49f30
								
							
						
					
					
						commit
						3aa4755876
					
				| 
						 | 
				
			
			@ -219,7 +219,7 @@ void Bar::_init_imgages() {
 | 
			
		|||
            int h = fm.height();
 | 
			
		||||
            if(h < m_res[res_chkbox_normal].height())
 | 
			
		||||
                h = m_res[res_chkbox_normal].height();
 | 
			
		||||
            m_rc_skip = QRect(0, 0, fm.width("无操作则跳过") + CHKBOX_RIGHT_PADDING + m_res[res_chkbox_normal].width(), h);
 | 
			
		||||
            m_rc_skip = QRect(0, 0, fm.width(LOCAL8BIT("无操作则跳过")) + CHKBOX_RIGHT_PADDING + m_res[res_chkbox_normal].width(), h);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int w = m_rc_skip.width();
 | 
			
		||||
| 
						 | 
				
			
			@ -254,7 +254,7 @@ void Bar::_init_imgages() {
 | 
			
		|||
                    img = &m_res[res_chkbox_normal];
 | 
			
		||||
                }
 | 
			
		||||
                ps.drawPixmap(0, chkbox_top, img->width(), img->height(), *img);
 | 
			
		||||
                ps.drawText(QRect(text_left, text_top, w-text_left, h-text_top), Qt::AlignCenter, "无操作则跳过");
 | 
			
		||||
                ps.drawText(QRect(text_left, text_top, w-text_left, h-text_top), Qt::AlignCenter, LOCAL8BIT("无操作则跳过"));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -187,7 +187,7 @@ void MainWindow::_start_play_thread() {
 | 
			
		|||
        m_thr_play = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_thr_play = new ThrPlay();
 | 
			
		||||
    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());
 | 
			
		||||
| 
						 | 
				
			
			@ -340,6 +340,11 @@ void MainWindow::_do_update_data(UpdateData* dat) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    else if(dat->data_type() == TYPE_MESSAGE) {
 | 
			
		||||
        if(dat->message().isEmpty()) {
 | 
			
		||||
            m_show_message = false;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_show_message = true;
 | 
			
		||||
 | 
			
		||||
        qDebug("1message, w=%d, h=%d", m_canvas.width(), m_canvas.height());
 | 
			
		||||
| 
						 | 
				
			
			@ -430,10 +435,14 @@ void MainWindow::_do_update_data(UpdateData* dat) {
 | 
			
		|||
        m_timer_bar_delay_hide.start(2000);
 | 
			
		||||
 | 
			
		||||
        QString title;
 | 
			
		||||
        if (m_rec_hdr.basic.conn_port == 3389)
 | 
			
		||||
            title.sprintf("[%s] %s@%s [Teleport-RDP录像回放]", m_rec_hdr.basic.acc_username, m_rec_hdr.basic.user_username, m_rec_hdr.basic.conn_ip);
 | 
			
		||||
        else
 | 
			
		||||
            title.sprintf("[%s] %s@%s:%d [Teleport-RDP录像回放]", m_rec_hdr.basic.acc_username, m_rec_hdr.basic.user_username, m_rec_hdr.basic.conn_ip, m_rec_hdr.basic.conn_port);
 | 
			
		||||
        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));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            QString _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));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        setWindowTitle(title);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,6 +39,9 @@ public:
 | 
			
		|||
//    Downloader* downloader() {return m_dl;}
 | 
			
		||||
//    void reset_downloader() {if(m_dl){delete m_dl;m_dl= nullptr;}}
 | 
			
		||||
 | 
			
		||||
    // TODO: 将thr_data移动到thr_play线程,由play线程进行管理
 | 
			
		||||
    ThrData* get_thr_data() {return m_thr_data;}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void paintEvent(QPaintEvent *e);
 | 
			
		||||
    void mouseMoveEvent(QMouseEvent *e);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,11 @@
 | 
			
		|||
 | 
			
		||||
#include <Qt>
 | 
			
		||||
 | 
			
		||||
#define TS_TPPR_TYPE_UNKNOWN    0x0000
 | 
			
		||||
#define TS_TPPR_TYPE_SSH        0x0001
 | 
			
		||||
#define TS_TPPR_TYPE_RDP        0x0101
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define TS_RECORD_TYPE_RDP_POINTER          0x12    // 鼠标坐标位置改变,用于绘制虚拟鼠标
 | 
			
		||||
#define TS_RECORD_TYPE_RDP_IMAGE            0x13    // 服务端返回的图像,用于展示
 | 
			
		||||
#define TS_RECORD_TYPE_RDP_KEYFRAME         0x14    //
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
#include <QNetworkCookie>
 | 
			
		||||
#include <QStandardPaths>
 | 
			
		||||
#include <qcoreapplication.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
#include "thr_play.h"
 | 
			
		||||
#include "thr_data.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -25,12 +26,12 @@ ThrData::ThrData(MainWindow* mainwin, const QString& res) {
 | 
			
		|||
//    m_dl = nullptr;
 | 
			
		||||
 | 
			
		||||
#ifdef __APPLE__
 | 
			
		||||
    QString data_path_base = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
 | 
			
		||||
    data_path_base += "/tp-testdata/";
 | 
			
		||||
    m_data_path_base = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
 | 
			
		||||
    m_data_path_base += "/tp-testdata/";
 | 
			
		||||
#else
 | 
			
		||||
    m_local_data_path_base = QCoreApplication::applicationDirPath() + "/record";
 | 
			
		||||
    m_data_path_base = QCoreApplication::applicationDirPath() + "/record";
 | 
			
		||||
#endif
 | 
			
		||||
    qDebug("data-path-base: %s", m_local_data_path_base.toStdString().c_str());
 | 
			
		||||
    qDebug("data-path-base: %s", m_data_path_base.toStdString().c_str());
 | 
			
		||||
 | 
			
		||||
    //    qDebug() << "AppConfigLocation:" << QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
 | 
			
		||||
    //    qDebug() << "AppDataLocation:" << QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +51,7 @@ GenericCacheLocation: "C:/Users/apex/AppData/Local/cache"
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
ThrData::~ThrData() {
 | 
			
		||||
    _clear_data();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThrData::stop() {
 | 
			
		||||
| 
						 | 
				
			
			@ -72,224 +74,294 @@ void ThrData::_notify_error(const QString& msg) {
 | 
			
		|||
    emit signal_update_data(_msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//	tp-player.exe http://teleport.domain.com:7190/{sub/path/}tp_1491560510_ca67fceb75a78c9d/1234 (注意,并不直接访问此URI,实际上其并不存在)
 | 
			
		||||
//                TP服务器地址(可能包含子路径哦,例如上例中的{sub/path/}部分)/session-id(用于判断当前授权用户)/录像会话编号
 | 
			
		||||
 | 
			
		||||
void ThrData::run() {
 | 
			
		||||
    _run();
 | 
			
		||||
    qDebug("ThrData thread run() end.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThrData::_run() {
 | 
			
		||||
 | 
			
		||||
    QString _tmp_res = m_res.toLower();
 | 
			
		||||
    if(_tmp_res.startsWith("http")) {
 | 
			
		||||
        m_need_download = true;
 | 
			
		||||
        _notify_message(LOCAL8BIT("正在准备录像数据,请稍候..."));
 | 
			
		||||
 | 
			
		||||
        if(!m_thr_download.init(m_data_path_base, m_res)) {
 | 
			
		||||
            _notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("无法下载录像文件!\n\n"), m_res));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_thr_download.start();
 | 
			
		||||
        msleep(100);
 | 
			
		||||
 | 
			
		||||
        for(;;) {
 | 
			
		||||
            if(m_need_stop)
 | 
			
		||||
                return;
 | 
			
		||||
            if(!m_thr_download.is_running() || m_thr_download.is_tpk_downloaded())
 | 
			
		||||
                break;
 | 
			
		||||
            msleep(100);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!m_thr_download.is_tpk_downloaded())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        m_thr_download.get_data_path(m_data_path);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        QFileInfo fi_chk_link(m_res);
 | 
			
		||||
        if(fi_chk_link.isSymLink())
 | 
			
		||||
            m_res = fi_chk_link.symLinkTarget();
 | 
			
		||||
 | 
			
		||||
        QFileInfo fi(m_res);
 | 
			
		||||
        if(!fi.exists()) {
 | 
			
		||||
            _notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("指定的文件或目录不存在!"), m_res));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(fi.isFile()) {
 | 
			
		||||
            m_data_path = fi.path();
 | 
			
		||||
        }
 | 
			
		||||
        else if(fi.isDir()) {
 | 
			
		||||
            m_data_path = m_res;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_data_path = QDir::toNativeSeparators(m_data_path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 到这里,.tpr和.tpk文件均已经下载完成了。
 | 
			
		||||
 | 
			
		||||
    if(!_load_header())
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if(!_load_keyframe())
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    uint32_t file_idx = 0;
 | 
			
		||||
 | 
			
		||||
    UpdateData* dat = new UpdateData(TYPE_HEADER_INFO);
 | 
			
		||||
    dat->alloc_data(sizeof(TS_RECORD_HEADER));
 | 
			
		||||
    memcpy(dat->data_buf(), &m_hdr, sizeof(TS_RECORD_HEADER));
 | 
			
		||||
    emit signal_update_data(dat);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
    // fake-code:
 | 
			
		||||
    file_index = 0;
 | 
			
		||||
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        if(file_index >= file_count) {
 | 
			
		||||
            msleep(500);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if(queue.size < 500) {
 | 
			
		||||
            need_pkg = 1000 - queue.size;
 | 
			
		||||
 | 
			
		||||
            for(i = 0; i < need_pkg; i++) {
 | 
			
		||||
                if(f.not_open) {
 | 
			
		||||
                    f.open(file_index);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                pkg = read_pkg()
 | 
			
		||||
                if(f.to_end) {
 | 
			
		||||
                    f.close();
 | 
			
		||||
                    file_index += 1;
 | 
			
		||||
                    if(file_index >= file_count)
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                queue.add(pkg)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(file_index >= file_count)
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            msleep(100);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    QFile* fdata = nullptr;
 | 
			
		||||
    uint32_t file_idx = 0;
 | 
			
		||||
    uint32_t start_offset = 0;
 | 
			
		||||
    qint64 file_size = 0;
 | 
			
		||||
    qint64 file_processed = 0;
 | 
			
		||||
    qint64 read_len = 0;
 | 
			
		||||
    QString str_fidx;
 | 
			
		||||
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        // 任何时候确保第一时间响应退出操作
 | 
			
		||||
        if(m_need_stop)
 | 
			
		||||
            break;
 | 
			
		||||
        QString str_fidx;
 | 
			
		||||
        str_fidx.sprintf("%d", file_idx+1);
 | 
			
		||||
 | 
			
		||||
        QString tpd_fname = QString("%1/tp-rdp-%2.tpd").arg(m_path_base, str_fidx);
 | 
			
		||||
        tpd_fname = QDir::toNativeSeparators(tpd_fname);
 | 
			
		||||
 | 
			
		||||
        if(m_need_download) {
 | 
			
		||||
            QString tmp_fname = QString("%1/tp-rdp-%2.tpd.downloading").arg(m_path_base, str_fidx);
 | 
			
		||||
            tmp_fname = QDir::toNativeSeparators(tmp_fname);
 | 
			
		||||
 | 
			
		||||
            QFileInfo fi_tmp(tmp_fname);
 | 
			
		||||
            if(fi_tmp.isFile()) {
 | 
			
		||||
                QFile::remove(tmp_fname);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            QFileInfo fi_tpd(tpd_fname);
 | 
			
		||||
            if(!fi_tpd.exists()) {
 | 
			
		||||
                QString url = QString("%1/audit/get-file?act=read&type=rdp&rid=%2&f=tp-rdp-%3.tpd").arg(m_url_base, m_rid, str_fidx);
 | 
			
		||||
 | 
			
		||||
                qDebug() << "URL : " << url;
 | 
			
		||||
                qDebug() << "TPD : " << tmp_fname;
 | 
			
		||||
                if(!_download_file(url, tmp_fname))
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                if(!QFile::rename(tmp_fname, tpd_fname))
 | 
			
		||||
                    return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        qDebug() << "TPD: " << tpd_fname;
 | 
			
		||||
 | 
			
		||||
        QFile f_tpd(tpd_fname);
 | 
			
		||||
        if(!f_tpd.open(QFile::ReadOnly)) {
 | 
			
		||||
            qDebug() << "Can not open " << tpd_fname << " for read.";
 | 
			
		||||
            _notify_error(QString("%1\n\n%3").arg(LOCAL8BIT("无法打开录像数据文件!"), tpd_fname));
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // 如果所有文件都已经处理完了,则等待(可能用户会拖动滚动条,或者重新播放)
 | 
			
		||||
        if(file_idx >= m_hdr.info.dat_file_count) {
 | 
			
		||||
            msleep(500);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        qint64 filesize = f_tpd.size();
 | 
			
		||||
        qint64 processed = 0;
 | 
			
		||||
        // 看看待播放队列中还有多少个数据包
 | 
			
		||||
        int pkg_count_in_queue = 0;
 | 
			
		||||
        int pkg_need_add = 0;
 | 
			
		||||
 | 
			
		||||
        // 加载并解析到待播放队列
 | 
			
		||||
        qint64 read_len = 0;
 | 
			
		||||
        for(;;) {
 | 
			
		||||
            {
 | 
			
		||||
//                if(m_need_stop)
 | 
			
		||||
//                    break;
 | 
			
		||||
        m_locker.lock();
 | 
			
		||||
        pkg_count_in_queue = m_data.size();
 | 
			
		||||
        m_locker.unlock();
 | 
			
		||||
 | 
			
		||||
//                m_locker.lock();
 | 
			
		||||
        // 少于500个的话,补足到1000个
 | 
			
		||||
        if(m_data.size() < 500)
 | 
			
		||||
            pkg_need_add = 1000 - pkg_count_in_queue;
 | 
			
		||||
 | 
			
		||||
//                if(m_data.size() > 500) {
 | 
			
		||||
//                    msleep(1000);
 | 
			
		||||
//                    continue;
 | 
			
		||||
//                }
 | 
			
		||||
        if(pkg_need_add == 0) {
 | 
			
		||||
            msleep(100);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//                m_locker.unlock();
 | 
			
		||||
        for(int i = 0; i < pkg_need_add; ++i) {
 | 
			
		||||
            if(m_need_stop)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            // 如果数据文件尚未打开,则打开它
 | 
			
		||||
            if(fdata == nullptr) {
 | 
			
		||||
                str_fidx.sprintf("%d", file_idx+1);
 | 
			
		||||
                QString tpd_fname = QString("%1/tp-rdp-%2.tpd").arg(m_data_path, str_fidx);
 | 
			
		||||
                tpd_fname = QDir::toNativeSeparators(tpd_fname);
 | 
			
		||||
 | 
			
		||||
                QFileInfo fi_tpd(tpd_fname);
 | 
			
		||||
                if(!fi_tpd.exists()) {
 | 
			
		||||
                    if(m_need_download) {
 | 
			
		||||
                        // 此文件尚未下载完成,等待
 | 
			
		||||
                        for(;;) {
 | 
			
		||||
                            if(m_need_stop)
 | 
			
		||||
                                return;
 | 
			
		||||
                            if(!m_thr_download.is_running() || m_thr_download.is_tpd_downloaded(file_idx))
 | 
			
		||||
                                break;
 | 
			
		||||
                            msleep(100);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        // 下载失败了
 | 
			
		||||
                        if(!m_thr_download.is_tpd_downloaded(file_idx))
 | 
			
		||||
                            return;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                fdata = new QFile(tpd_fname);
 | 
			
		||||
                if(!fdata->open(QFile::ReadOnly)) {
 | 
			
		||||
                    qDebug() << "Can not open " << tpd_fname << " for read.";
 | 
			
		||||
                    _notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("无法打开录像数据文件!"), tpd_fname));
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                file_size = fdata->size();
 | 
			
		||||
                file_processed = 0;
 | 
			
		||||
                qDebug("Open file, processed: %" PRId64 ", size: %" PRId64, file_processed, file_size);
 | 
			
		||||
            }
 | 
			
		||||
//            qDebug("B processed: %" PRId64 ", size: %" PRId64, file_processed, file_size);
 | 
			
		||||
 | 
			
		||||
            if(filesize - processed < sizeof(TS_RECORD_PKG)) {
 | 
			
		||||
                qDebug("invaid tp-rdp-%d.tpd file, filesize=%d, processed=%d, need=%d.", file_idx+1, filesize, processed, sizeof(TS_RECORD_PKG));
 | 
			
		||||
                _notify_error(QString("%1\n\n%3").arg(LOCAL8BIT("错误的录像数据文件!"), tpd_fname));
 | 
			
		||||
            //----------------------------------
 | 
			
		||||
            // 读取一个数据包
 | 
			
		||||
            //----------------------------------
 | 
			
		||||
            if(file_size - file_processed < sizeof(TS_RECORD_PKG)) {
 | 
			
		||||
                qDebug("invaid tp-rdp-%d.tpd file, filesize=%" PRId64 ", processed=%" PRId64 ", need=%d.", file_idx+1, file_size, file_processed, sizeof(TS_RECORD_PKG));
 | 
			
		||||
                _notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            TS_RECORD_PKG pkg;
 | 
			
		||||
            read_len = f_tpd.read(reinterpret_cast<char*>(&pkg), sizeof(pkg));
 | 
			
		||||
            if(read_len == 0)
 | 
			
		||||
                break;
 | 
			
		||||
            read_len = fdata->read(reinterpret_cast<char*>(&pkg), sizeof(TS_RECORD_PKG));
 | 
			
		||||
    //        if(read_len == 0)
 | 
			
		||||
    //            break;
 | 
			
		||||
            if(read_len != sizeof(TS_RECORD_PKG)) {
 | 
			
		||||
                qDebug("invaid tp-rdp-%d.tpd file, read_len=%d (1).", file_idx+1, read_len);
 | 
			
		||||
                _notify_error(QString("%1\n\n%3").arg(LOCAL8BIT("错误的录像数据文件!"), tpd_fname));
 | 
			
		||||
                qDebug("invaid tp-rdp-%d.tpd file, read_len=%" PRId64 " (1).", file_idx+1, read_len);
 | 
			
		||||
                _notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            processed += sizeof(TS_RECORD_PKG);
 | 
			
		||||
            file_processed += sizeof(TS_RECORD_PKG);
 | 
			
		||||
 | 
			
		||||
            if(filesize - processed < pkg.size) {
 | 
			
		||||
            if(file_size - file_processed < pkg.size) {
 | 
			
		||||
                qDebug("invaid tp-rdp-%d.tpd file (2).", file_idx+1);
 | 
			
		||||
                _notify_error(QString("%1\n\n%3").arg(LOCAL8BIT("错误的录像数据文件!"), tpd_fname));
 | 
			
		||||
                _notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
 | 
			
		||||
                qDebug("----key frame: %d, pkg.size=%d", pkg.time_ms, pkg.size);
 | 
			
		||||
                if(pkg.size > 0) {
 | 
			
		||||
                    f_tpd.read(pkg.size);
 | 
			
		||||
                }
 | 
			
		||||
                continue;
 | 
			
		||||
            if(pkg.size == 0) {
 | 
			
		||||
                qDebug("################## too bad.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            UpdateData* dat = new UpdateData(TYPE_DATA);
 | 
			
		||||
            dat->alloc_data(sizeof(TS_RECORD_PKG) + pkg.size);
 | 
			
		||||
            memcpy(dat->data_buf(), &pkg, sizeof(TS_RECORD_PKG));
 | 
			
		||||
            read_len = f_tpd.read(reinterpret_cast<char*>(dat->data_buf()+sizeof(TS_RECORD_PKG)), pkg.size);
 | 
			
		||||
            read_len = fdata->read(reinterpret_cast<char*>(dat->data_buf()+sizeof(TS_RECORD_PKG)), pkg.size);
 | 
			
		||||
            if(read_len != pkg.size) {
 | 
			
		||||
                delete dat;
 | 
			
		||||
                qDebug("invaid tp-rdp-%d.tpd file (3).", file_idx+1);
 | 
			
		||||
                _notify_error(QString("%1\n\n%3").arg(LOCAL8BIT("错误的录像数据文件!"), tpd_fname));
 | 
			
		||||
                qDebug("invaid tp-rdp-%d.tpd file, read_len=%" PRId64 " (3).", file_idx+1, read_len);
 | 
			
		||||
                _notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            file_processed += pkg.size;
 | 
			
		||||
 | 
			
		||||
            // 跳过关键帧
 | 
			
		||||
            // TODO: 拖动滚动条后,需要显示一次关键帧数据,然后跳过后续关键帧。
 | 
			
		||||
            if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
 | 
			
		||||
                qDebug("----key frame: %ld, processed=%" PRId64 ", pkg.size=%d", pkg.time_ms, file_processed, pkg.size);
 | 
			
		||||
                delete dat;
 | 
			
		||||
                dat = nullptr;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            {
 | 
			
		||||
            // 数据放到待播放列表中
 | 
			
		||||
            if(dat) {
 | 
			
		||||
                m_locker.lock();
 | 
			
		||||
                m_data.enqueue(dat);
 | 
			
		||||
//                qDebug("data count: %d", m_data.size());
 | 
			
		||||
                qDebug("queue data count: %d", m_data.size());
 | 
			
		||||
                m_locker.unlock();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 如果此文件已经处理完毕,则关闭文件,这样下次处理一个新的文件
 | 
			
		||||
//            qDebug("C processed: %" PRId64 ", size: %" PRId64, file_processed, file_size);
 | 
			
		||||
            if(file_processed >= file_size) {
 | 
			
		||||
                fdata->close();
 | 
			
		||||
                delete fdata;
 | 
			
		||||
                fdata = nullptr;
 | 
			
		||||
                file_idx++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(file_idx >= m_hdr.info.dat_file_count) {
 | 
			
		||||
                UpdateData* dat = new UpdateData(TYPE_END);
 | 
			
		||||
                m_locker.lock();
 | 
			
		||||
                m_data.enqueue(dat);
 | 
			
		||||
                qDebug("queue data count: %d", m_data.size());
 | 
			
		||||
                m_locker.unlock();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        file_idx += 1;
 | 
			
		||||
        if(file_idx >= m_hdr.info.dat_file_count)
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ThrData::_load_header() {
 | 
			
		||||
    QString msg;
 | 
			
		||||
    QString _tmp_res = m_res.toLower();
 | 
			
		||||
    qDebug() << "PATH_BASE: " << m_data_path;
 | 
			
		||||
 | 
			
		||||
    if(_tmp_res.startsWith("http")) {
 | 
			
		||||
        m_need_download = true;
 | 
			
		||||
    QString filename = QString("%1/tp-rdp.tpr").arg(m_data_path);
 | 
			
		||||
    filename = QDir::toNativeSeparators(filename);
 | 
			
		||||
    qDebug() << "TPR: " << filename;
 | 
			
		||||
 | 
			
		||||
    QFile f(filename);
 | 
			
		||||
    if(!f.open(QFile::ReadOnly)) {
 | 
			
		||||
        qDebug() << "Can not open " << filename << " for read.";
 | 
			
		||||
        _notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("无法打开录像信息文件!"), filename));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(m_need_download) {
 | 
			
		||||
        _notify_message(LOCAL8BIT("正在准备录像数据,请稍候..."));
 | 
			
		||||
    memset(&m_hdr, 0, sizeof(TS_RECORD_HEADER));
 | 
			
		||||
 | 
			
		||||
        QStringList _uris = m_res.split('/');
 | 
			
		||||
        if(_uris.size() < 3) {
 | 
			
		||||
            qDebug() << "invalid param: " << m_res;
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_sid = _uris[_uris.size()-2];
 | 
			
		||||
        m_rid = _uris[_uris.size()-1];
 | 
			
		||||
        m_url_base = m_res.left(m_res.length() - m_sid.length() - m_rid.length() - 2);
 | 
			
		||||
 | 
			
		||||
        qDebug() << "url-base:[" << m_url_base << "], sid:[" << m_sid << "], rid:[" << m_rid << "]";
 | 
			
		||||
 | 
			
		||||
        // download .tpr
 | 
			
		||||
        QString url = QString("%1/audit/get-file?act=read&type=rdp&rid=%2&f=tp-rdp.tpr").arg(m_url_base, m_rid);
 | 
			
		||||
        QByteArray data;
 | 
			
		||||
        if(!_download_file(url, data))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if(data.size() != sizeof(TS_RECORD_HEADER)) {
 | 
			
		||||
            qDebug("invalid header file. %d", data.size());
 | 
			
		||||
            _notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("指定的文件或目录不存在!"), _tmp_res));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        memcpy(&m_hdr, data.data(), sizeof(TS_RECORD_HEADER));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        QFileInfo fi_chk_link(m_res);
 | 
			
		||||
        if(fi_chk_link.isSymLink())
 | 
			
		||||
            _tmp_res = fi_chk_link.symLinkTarget();
 | 
			
		||||
        else
 | 
			
		||||
            _tmp_res = m_res;
 | 
			
		||||
 | 
			
		||||
        QFileInfo fi(_tmp_res);
 | 
			
		||||
        if(!fi.exists()) {
 | 
			
		||||
            _notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("指定的文件或目录不存在!"), _tmp_res));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(fi.isFile()) {
 | 
			
		||||
            m_path_base = fi.path();
 | 
			
		||||
        }
 | 
			
		||||
        else if(fi.isDir()) {
 | 
			
		||||
            m_path_base = _tmp_res;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_path_base = QDir::toNativeSeparators(m_path_base);
 | 
			
		||||
 | 
			
		||||
        qDebug() << "PATH_BASE: " << m_path_base;
 | 
			
		||||
 | 
			
		||||
        QString filename = QString("%1/tp-rdp.tpr").arg(m_path_base);
 | 
			
		||||
        filename = QDir::toNativeSeparators(filename);
 | 
			
		||||
        qDebug() << "TPR: " << filename;
 | 
			
		||||
 | 
			
		||||
        QFile f(filename);
 | 
			
		||||
        if(!f.open(QFile::ReadOnly)) {
 | 
			
		||||
            qDebug() << "Can not open " << filename << " for read.";
 | 
			
		||||
            _notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("无法打开录像信息文件!"), filename));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        memset(&m_hdr, 0, sizeof(TS_RECORD_HEADER));
 | 
			
		||||
 | 
			
		||||
        qint64 read_len = 0;
 | 
			
		||||
        read_len = f.read(reinterpret_cast<char*>(&m_hdr), sizeof(TS_RECORD_HEADER));
 | 
			
		||||
        if(read_len != sizeof(TS_RECORD_HEADER)) {
 | 
			
		||||
            qDebug() << "invaid .tpr file.";
 | 
			
		||||
            _notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("错误的录像信息文件!"), filename));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    qint64 read_len = 0;
 | 
			
		||||
    read_len = f.read(reinterpret_cast<char*>(&m_hdr), sizeof(TS_RECORD_HEADER));
 | 
			
		||||
    if(read_len != sizeof(TS_RECORD_HEADER)) {
 | 
			
		||||
        qDebug() << "invaid .tpr file.";
 | 
			
		||||
        _notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("错误的录像信息文件!"), filename));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(m_hdr.info.ver != 4) {
 | 
			
		||||
| 
						 | 
				
			
			@ -308,94 +380,13 @@ bool ThrData::_load_header() {
 | 
			
		|||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // 下载得到的数据应该是一个TS_RECORD_HEADER,解析此数据,生成本地文件路径,并保存之。
 | 
			
		||||
    if(m_need_download) {
 | 
			
		||||
        QDateTime timeUTC;
 | 
			
		||||
        //        timeUTC.setTimeSpec(Qt::UTC);
 | 
			
		||||
        //        timeUTC.setTime_t(m_hdr.basic.timestamp);
 | 
			
		||||
        timeUTC.setSecsSinceEpoch(m_hdr.basic.timestamp);
 | 
			
		||||
        QString strUTC = timeUTC.toString("yyyyMMdd-hhmmss");
 | 
			
		||||
 | 
			
		||||
        QString strAcc(m_hdr.basic.acc_username);
 | 
			
		||||
        int idx = strAcc.indexOf('\\');
 | 
			
		||||
        if(-1 != idx) {
 | 
			
		||||
            QString _domain = strAcc.left(idx);
 | 
			
		||||
            QString _user = strAcc.right(strAcc.length() - idx - 1);
 | 
			
		||||
            strAcc = _user + "@" + _domain;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // .../record/RDP-211-admin-user@domain-192.168.0.68-20191015-020243
 | 
			
		||||
        m_path_base = QString("%1/RDP-%2-%3-%4-%5-%6").arg(m_local_data_path_base,
 | 
			
		||||
                                                           m_rid,
 | 
			
		||||
                                                           m_hdr.basic.user_username,
 | 
			
		||||
                                                           strAcc,
 | 
			
		||||
                                                           m_hdr.basic.host_ip,
 | 
			
		||||
                                                           strUTC
 | 
			
		||||
                                                           );
 | 
			
		||||
 | 
			
		||||
        m_path_base = QDir::toNativeSeparators(m_path_base);
 | 
			
		||||
 | 
			
		||||
        qDebug() << "PATH_BASE: " << m_path_base;
 | 
			
		||||
 | 
			
		||||
        QDir dir;
 | 
			
		||||
        dir.mkpath(m_path_base);
 | 
			
		||||
        QFileInfo fi;
 | 
			
		||||
        fi.setFile(m_path_base);
 | 
			
		||||
        if(!fi.isDir()) {
 | 
			
		||||
            qDebug("can not create folder to save downloaded file.");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        QString filename = QString("%1/tp-rdp.tpr").arg(m_path_base);
 | 
			
		||||
        filename = QDir::toNativeSeparators(filename);
 | 
			
		||||
        qDebug() << "TPR: " << filename;
 | 
			
		||||
 | 
			
		||||
        QFile f;
 | 
			
		||||
        f.setFileName(filename);
 | 
			
		||||
        if(!f.open(QIODevice::WriteOnly | QFile::Truncate)){
 | 
			
		||||
            qDebug("open file for write failed.");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        qint64 written = f.write(reinterpret_cast<const char*>(&m_hdr), sizeof(TS_RECORD_HEADER));
 | 
			
		||||
        f.flush();
 | 
			
		||||
        f.close();
 | 
			
		||||
 | 
			
		||||
        if(written != sizeof(TS_RECORD_HEADER)) {
 | 
			
		||||
            qDebug("save header file failed.");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ThrData::_load_keyframe() {
 | 
			
		||||
    QString tpk_fname = QString("%1/tp-rdp.tpk").arg(m_path_base);
 | 
			
		||||
    QString tpk_fname = QString("%1/tp-rdp.tpk").arg(m_data_path);
 | 
			
		||||
    tpk_fname = QDir::toNativeSeparators(tpk_fname);
 | 
			
		||||
 | 
			
		||||
    if(m_need_download) {
 | 
			
		||||
        QString tmp_fname = QString("%1/tp-rdp.tpk.downloading").arg(m_path_base);
 | 
			
		||||
        tmp_fname = QDir::toNativeSeparators(tmp_fname);
 | 
			
		||||
 | 
			
		||||
        QFileInfo fi_tmp(tmp_fname);
 | 
			
		||||
        if(fi_tmp.isFile()) {
 | 
			
		||||
            QFile::remove(tmp_fname);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        QFileInfo fi_tpk(tpk_fname);
 | 
			
		||||
        if(!fi_tpk.exists()) {
 | 
			
		||||
            QString url = QString("%1/audit/get-file?act=read&type=rdp&rid=%2&f=tp-rdp.tpk").arg(m_url_base, m_rid);
 | 
			
		||||
            qDebug() << "TPK: " << tmp_fname;
 | 
			
		||||
            if(!_download_file(url, tmp_fname))
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            if(!QFile::rename(tmp_fname, tpk_fname))
 | 
			
		||||
                return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qDebug() << "TPK: " << tpk_fname;
 | 
			
		||||
 | 
			
		||||
    QFile f_kf(tpk_fname);
 | 
			
		||||
| 
						 | 
				
			
			@ -430,40 +421,6 @@ bool ThrData::_load_keyframe() {
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ThrData::_download_file(const QString& url, const QString filename) {
 | 
			
		||||
    if(!m_need_download) {
 | 
			
		||||
        qDebug() << "download not necessary.";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Downloader dl;
 | 
			
		||||
    if(!dl.request(url, m_sid, filename)) {
 | 
			
		||||
        qDebug() << "download failed.";
 | 
			
		||||
        _notify_error(QString("%1").arg(LOCAL8BIT("下载文件失败!")));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ThrData::_download_file(const QString& url, QByteArray& data) {
 | 
			
		||||
    if(!m_need_download) {
 | 
			
		||||
        qDebug() << "download not necessary.";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Downloader dl;
 | 
			
		||||
 | 
			
		||||
    if(!dl.request(url, m_sid, &data)) {
 | 
			
		||||
        qDebug() << "download failed.";
 | 
			
		||||
        _notify_error(QString("%1").arg(LOCAL8BIT("下载文件失败!")));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void ThrData::_prepare() {
 | 
			
		||||
    UpdateData* d = new UpdateData(TYPE_HEADER_INFO);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -473,10 +430,21 @@ void ThrData::_prepare() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
UpdateData* ThrData::get_data() {
 | 
			
		||||
    UpdateData* d = nullptr;
 | 
			
		||||
 | 
			
		||||
    m_locker.lock();
 | 
			
		||||
    UpdateData* d = m_data.dequeue();
 | 
			
		||||
    if(m_data.size() > 0)
 | 
			
		||||
        d = m_data.dequeue();
 | 
			
		||||
    m_locker.unlock();
 | 
			
		||||
 | 
			
		||||
    return d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThrData::_clear_data() {
 | 
			
		||||
    m_locker.lock();
 | 
			
		||||
    while(m_data.size() > 0) {
 | 
			
		||||
        UpdateData* d = m_data.dequeue();
 | 
			
		||||
        delete d;
 | 
			
		||||
    }
 | 
			
		||||
    m_locker.unlock();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@
 | 
			
		|||
#include <QEventLoop>
 | 
			
		||||
#include "update_data.h"
 | 
			
		||||
#include "record_format.h"
 | 
			
		||||
#include "thr_download.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
为支持“边下载,边播放”、“可拖动进度条”等功能,录像数据会分为多个文件存放,目前每个文件约4MB。
 | 
			
		||||
| 
						 | 
				
			
			@ -63,9 +64,8 @@ private:
 | 
			
		|||
 | 
			
		||||
    bool _load_header();
 | 
			
		||||
    bool _load_keyframe();
 | 
			
		||||
    bool _download_file(const QString& url, const QString filename);
 | 
			
		||||
    bool _download_file(const QString& url, QByteArray& data);
 | 
			
		||||
 | 
			
		||||
    void _clear_data();
 | 
			
		||||
    void _prepare();
 | 
			
		||||
 | 
			
		||||
    void _notify_message(const QString& msg);
 | 
			
		||||
| 
						 | 
				
			
			@ -79,16 +79,18 @@ private:
 | 
			
		|||
    QQueue<UpdateData*> m_data;
 | 
			
		||||
    QMutex m_locker;
 | 
			
		||||
 | 
			
		||||
    ThrDownload m_thr_download;
 | 
			
		||||
 | 
			
		||||
    bool m_need_stop;
 | 
			
		||||
 | 
			
		||||
    bool m_need_download;
 | 
			
		||||
    QString m_res;
 | 
			
		||||
    QString m_local_data_path_base;
 | 
			
		||||
    QString m_data_path_base;
 | 
			
		||||
 | 
			
		||||
    QString m_url_base;
 | 
			
		||||
    QString m_sid;
 | 
			
		||||
    QString m_rid;
 | 
			
		||||
    QString m_path_base;
 | 
			
		||||
    QString m_data_path;
 | 
			
		||||
 | 
			
		||||
    TS_RECORD_HEADER m_hdr;
 | 
			
		||||
    KeyFrames m_kf;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,292 @@
 | 
			
		|||
#include <QDebug>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QNetworkCookie>
 | 
			
		||||
 | 
			
		||||
#include "thr_download.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "downloader.h"
 | 
			
		||||
#include "record_format.h"
 | 
			
		||||
 | 
			
		||||
//=================================================================
 | 
			
		||||
// ThrDownload
 | 
			
		||||
//=================================================================
 | 
			
		||||
 | 
			
		||||
ThrDownload::ThrDownload() {
 | 
			
		||||
    m_need_stop = false;
 | 
			
		||||
    m_have_tpr = false;
 | 
			
		||||
    m_have_tpk = false;
 | 
			
		||||
    m_have_tpd = nullptr;
 | 
			
		||||
    m_need_tpk = false;
 | 
			
		||||
    m_running = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ThrDownload::~ThrDownload() {
 | 
			
		||||
    if(m_have_tpd)
 | 
			
		||||
        delete[] m_have_tpd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//	tp-player.exe http://teleport.domain.com:7190/{sub/path/}tp_1491560510_ca67fceb75a78c9d/1234 (注意,并不直接访问此URI,实际上其并不存在)
 | 
			
		||||
//                TP服务器地址(可能包含子路径哦,例如上例中的{sub/path/}部分)/session-id(用于判断当前授权用户)/录像会话编号
 | 
			
		||||
 | 
			
		||||
bool ThrDownload::init(const QString& local_data_path_base, const QString &res) {
 | 
			
		||||
    m_data_path_base = local_data_path_base;
 | 
			
		||||
 | 
			
		||||
    QString _tmp_res = res.toLower();
 | 
			
		||||
    if(!_tmp_res.startsWith("http")) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QStringList _uris = res.split('/');
 | 
			
		||||
    if(_uris.size() < 3) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_sid = _uris[_uris.size()-2];
 | 
			
		||||
    m_rid = _uris[_uris.size()-1];
 | 
			
		||||
    m_url_base = res.left(res.length() - m_sid.length() - m_rid.length() - 2);
 | 
			
		||||
 | 
			
		||||
    if(m_sid.length() == 0 || m_rid.length() == 0 || m_url_base.length() == 0)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThrDownload::stop() {
 | 
			
		||||
    if(!m_running)
 | 
			
		||||
        return;
 | 
			
		||||
//    if(!isRunning())
 | 
			
		||||
//        return;
 | 
			
		||||
    m_need_stop = true;
 | 
			
		||||
    wait();
 | 
			
		||||
    qDebug("data thread stop() end.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//	tp-player.exe http://teleport.domain.com:7190/{sub/path/}tp_1491560510_ca67fceb75a78c9d/1234 (注意,并不直接访问此URI,实际上其并不存在)
 | 
			
		||||
//                TP服务器地址(可能包含子路径哦,例如上例中的{sub/path/}部分)/session-id(用于判断当前授权用户)/录像会话编号
 | 
			
		||||
 | 
			
		||||
void ThrDownload::run() {
 | 
			
		||||
    _run();
 | 
			
		||||
    m_running = false;
 | 
			
		||||
    qDebug("ThrDownload thread run() end.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThrDownload::_run() {
 | 
			
		||||
//    m_state = statDownloading;
 | 
			
		||||
 | 
			
		||||
    if(!_download_tpr()) {
 | 
			
		||||
//        m_state = statFailDone;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    m_have_tpr = true;
 | 
			
		||||
 | 
			
		||||
    m_have_tpd = new bool[m_tpd_count];
 | 
			
		||||
    for(uint32_t i = 0; i < m_tpd_count; ++i) {
 | 
			
		||||
        m_have_tpd[i] = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(m_need_tpk) {
 | 
			
		||||
        if(!_download_tpk()) {
 | 
			
		||||
//            m_state = statFailDone;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        m_have_tpk = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t file_idx = 0;
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        if(m_need_stop)
 | 
			
		||||
            break;
 | 
			
		||||
        QString str_fidx;
 | 
			
		||||
        str_fidx.sprintf("%d", file_idx+1);
 | 
			
		||||
 | 
			
		||||
        QString tpd_fname = QString("%1/tp-rdp-%2.tpd").arg(m_data_path, str_fidx);
 | 
			
		||||
        tpd_fname = QDir::toNativeSeparators(tpd_fname);
 | 
			
		||||
 | 
			
		||||
        QString tmp_fname = QString("%1/tp-rdp-%2.tpd.downloading").arg(m_data_path, str_fidx);
 | 
			
		||||
        tmp_fname = QDir::toNativeSeparators(tmp_fname);
 | 
			
		||||
 | 
			
		||||
        QFileInfo fi_tmp(tmp_fname);
 | 
			
		||||
        if(fi_tmp.isFile()) {
 | 
			
		||||
            QFile::remove(tmp_fname);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        QFileInfo fi_tpd(tpd_fname);
 | 
			
		||||
        if(!fi_tpd.exists()) {
 | 
			
		||||
            QString url = QString("%1/audit/get-file?act=read&type=rdp&rid=%2&f=tp-rdp-%3.tpd").arg(m_url_base, m_rid, str_fidx);
 | 
			
		||||
 | 
			
		||||
            qDebug() << "URL : " << url;
 | 
			
		||||
            qDebug() << "TPD : " << tmp_fname;
 | 
			
		||||
            if(!_download_file(url, tmp_fname)) {
 | 
			
		||||
//                m_state = statFailDone;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(!QFile::rename(tmp_fname, tpd_fname)) {
 | 
			
		||||
//                m_state = statFailDone;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_have_tpd[file_idx] = true;
 | 
			
		||||
 | 
			
		||||
        file_idx += 1;
 | 
			
		||||
        if(file_idx >= m_tpd_count)
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//    m_state = statSuccessDone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ThrDownload::_download_tpr() {
 | 
			
		||||
    QString url = QString("%1/audit/get-file?act=read&type=rdp&rid=%2&f=tp-rdp.tpr").arg(m_url_base, m_rid);
 | 
			
		||||
    QByteArray data;
 | 
			
		||||
    if(!_download_file(url, data))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    if(data.size() != sizeof(TS_RECORD_HEADER)) {
 | 
			
		||||
        qDebug("invalid header data. %d", data.size());
 | 
			
		||||
        m_error = QString(LOCAL8BIT("录像信息文件数据错误!"));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TS_RECORD_HEADER* hdr = reinterpret_cast<TS_RECORD_HEADER*>(data.data());
 | 
			
		||||
//    if(hdr->info.ver != 4) {
 | 
			
		||||
//        qDebug() << "invaid .tpr file.";
 | 
			
		||||
//        m_last_error = QString("%1 %2%3").arg(LOCAL8BIT("不支持的录像文件版本 "), QString(hdr->info.ver), LOCAL8BIT("!\n\n此播放器支持录像文件版本 4。"));
 | 
			
		||||
//        return false;
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
//    if(m_hdr.basic.width == 0 || m_hdr.basic.height == 0) {
 | 
			
		||||
//        _notify_error(LOCAL8BIT("错误的录像信息,未记录窗口尺寸!"));
 | 
			
		||||
//        return false;
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
//    if(m_hdr.info.dat_file_count == 0) {
 | 
			
		||||
//        _notify_error(LOCAL8BIT("错误的录像信息,未记录数据文件数量!"));
 | 
			
		||||
//        return false;
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // 下载得到的数据应该是一个TS_RECORD_HEADER,解析此数据,生成本地文件路径,并保存之。
 | 
			
		||||
    QDateTime timeUTC;
 | 
			
		||||
    //        timeUTC.setTimeSpec(Qt::UTC);
 | 
			
		||||
    //        timeUTC.setTime_t(m_hdr.basic.timestamp);
 | 
			
		||||
    timeUTC.setSecsSinceEpoch(hdr->basic.timestamp);
 | 
			
		||||
    QString strUTC = timeUTC.toString("yyyyMMdd-hhmmss");
 | 
			
		||||
 | 
			
		||||
    QString strAcc(hdr->basic.acc_username);
 | 
			
		||||
    int idx = strAcc.indexOf('\\');
 | 
			
		||||
    if(-1 != idx) {
 | 
			
		||||
        QString _domain = strAcc.left(idx);
 | 
			
		||||
        QString _user = strAcc.right(strAcc.length() - idx - 1);
 | 
			
		||||
        strAcc = _user + "@" + _domain;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString strType;
 | 
			
		||||
    if(hdr->info.type == TS_TPPR_TYPE_SSH) {
 | 
			
		||||
        strType = "SSH";
 | 
			
		||||
    }
 | 
			
		||||
    else if(hdr->info.type == TS_TPPR_TYPE_RDP) {
 | 
			
		||||
        strType = "RDP";
 | 
			
		||||
        m_need_tpk = true;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        strType = "UNKNOWN";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // .../record/RDP-211-admin-user@domain-192.168.0.68-20191015-020243
 | 
			
		||||
    m_data_path = QString("%1/%2-%3-%4-%5-%6-%7").arg(m_data_path_base, strType, m_rid, hdr->basic.user_username, strAcc, hdr->basic.host_ip, strUTC);
 | 
			
		||||
    m_data_path = QDir::toNativeSeparators(m_data_path);
 | 
			
		||||
    qDebug() << "PATH_BASE: " << m_data_path;
 | 
			
		||||
 | 
			
		||||
    QDir dir;
 | 
			
		||||
    dir.mkpath(m_data_path);
 | 
			
		||||
    QFileInfo fi;
 | 
			
		||||
    fi.setFile(m_data_path);
 | 
			
		||||
    if(!fi.isDir()) {
 | 
			
		||||
        qDebug("can not create folder to save downloaded file.");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString filename = QString("%1/tp-rdp.tpr").arg(m_data_path);
 | 
			
		||||
    filename = QDir::toNativeSeparators(filename);
 | 
			
		||||
    qDebug() << "TPR: " << filename;
 | 
			
		||||
 | 
			
		||||
    QFile f;
 | 
			
		||||
    f.setFileName(filename);
 | 
			
		||||
    if(!f.open(QIODevice::WriteOnly | QFile::Truncate)){
 | 
			
		||||
        qDebug("open file for write failed.");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qint64 written = f.write(reinterpret_cast<const char*>(hdr), sizeof(TS_RECORD_HEADER));
 | 
			
		||||
    f.flush();
 | 
			
		||||
    f.close();
 | 
			
		||||
 | 
			
		||||
    if(written != sizeof(TS_RECORD_HEADER)) {
 | 
			
		||||
        qDebug("save header file failed.");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_tpd_count = hdr->info.dat_file_count;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ThrDownload::_download_tpk() {
 | 
			
		||||
    QString tpk_fname = QString("%1/tp-rdp.tpk").arg(m_data_path);
 | 
			
		||||
    tpk_fname = QDir::toNativeSeparators(tpk_fname);
 | 
			
		||||
 | 
			
		||||
    QString tmp_fname = QString("%1/tp-rdp.tpk.downloading").arg(m_data_path);
 | 
			
		||||
    tmp_fname = QDir::toNativeSeparators(tmp_fname);
 | 
			
		||||
 | 
			
		||||
    QFileInfo fi_tmp(tmp_fname);
 | 
			
		||||
    if(fi_tmp.isFile()) {
 | 
			
		||||
        QFile::remove(tmp_fname);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QFileInfo fi_tpk(tpk_fname);
 | 
			
		||||
    if(!fi_tpk.exists()) {
 | 
			
		||||
        QString url = QString("%1/audit/get-file?act=read&type=rdp&rid=%2&f=tp-rdp.tpk").arg(m_url_base, m_rid);
 | 
			
		||||
        qDebug() << "TPK: " << tmp_fname;
 | 
			
		||||
        if(!_download_file(url, tmp_fname))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if(!QFile::rename(tmp_fname, tpk_fname))
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ThrDownload::_download_file(const QString& url, const QString filename) {
 | 
			
		||||
    Downloader dl;
 | 
			
		||||
    if(!dl.request(url, m_sid, filename)) {
 | 
			
		||||
        qDebug() << "download failed.";
 | 
			
		||||
        m_error = QString("%1").arg(LOCAL8BIT("下载文件失败!"));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ThrDownload::_download_file(const QString& url, QByteArray& data) {
 | 
			
		||||
    Downloader dl;
 | 
			
		||||
    if(!dl.request(url, m_sid, &data)) {
 | 
			
		||||
        qDebug() << "download failed.";
 | 
			
		||||
        m_error = QString("%1").arg(LOCAL8BIT("下载文件失败!"));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ThrDownload::is_tpd_downloaded(uint32_t file_idx) const {
 | 
			
		||||
    if(!m_have_tpd)
 | 
			
		||||
        return false;
 | 
			
		||||
    if(file_idx >= m_tpd_count)
 | 
			
		||||
        return false;
 | 
			
		||||
    return m_have_tpd[file_idx];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
#ifndef THR_DOWNLOAD_H
 | 
			
		||||
#define THR_DOWNLOAD_H
 | 
			
		||||
 | 
			
		||||
#include <QThread>
 | 
			
		||||
#include <QNetworkReply>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QEventLoop>
 | 
			
		||||
 | 
			
		||||
class ThrDownload : public QThread {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
//public:
 | 
			
		||||
//    enum State {
 | 
			
		||||
//        statStarting,
 | 
			
		||||
//        statDownloading,
 | 
			
		||||
//        statInvalidParam,
 | 
			
		||||
//        statFailDone,
 | 
			
		||||
//        statSuccessDone
 | 
			
		||||
//    };
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    ThrDownload();
 | 
			
		||||
    ~ThrDownload();
 | 
			
		||||
 | 
			
		||||
    bool init(const QString& local_data_path_base, const QString& res);
 | 
			
		||||
 | 
			
		||||
    virtual void run();
 | 
			
		||||
    void stop();
 | 
			
		||||
 | 
			
		||||
    bool is_running() const {return m_running;}
 | 
			
		||||
 | 
			
		||||
    bool is_tpr_downloaded() const {return m_have_tpr;}
 | 
			
		||||
    bool is_tpk_downloaded() const {return m_have_tpk;}
 | 
			
		||||
    bool is_tpd_downloaded(uint32_t file_idx) const;
 | 
			
		||||
    bool get_data_path(QString& path) const {
 | 
			
		||||
        if(m_data_path.isEmpty())
 | 
			
		||||
            return false;
 | 
			
		||||
        path = m_data_path;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void _run();
 | 
			
		||||
 | 
			
		||||
    bool _download_tpr();
 | 
			
		||||
    bool _download_tpk();
 | 
			
		||||
 | 
			
		||||
    bool _download_file(const QString& url, const QString filename);
 | 
			
		||||
    bool _download_file(const QString& url, QByteArray& data);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    bool m_need_stop;
 | 
			
		||||
 | 
			
		||||
    QString m_data_path_base;
 | 
			
		||||
 | 
			
		||||
    QString m_url_base;
 | 
			
		||||
    QString m_sid;
 | 
			
		||||
    QString m_rid;
 | 
			
		||||
    QString m_data_path;
 | 
			
		||||
 | 
			
		||||
    bool m_running;
 | 
			
		||||
    bool m_have_tpr;
 | 
			
		||||
    bool m_have_tpk;
 | 
			
		||||
    bool m_need_tpk;
 | 
			
		||||
 | 
			
		||||
    uint32_t m_tpd_count;
 | 
			
		||||
    bool* m_have_tpd;
 | 
			
		||||
 | 
			
		||||
    QString m_error;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // THR_DOWNLOAD_H
 | 
			
		||||
| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
 | 
			
		||||
#include "thr_play.h"
 | 
			
		||||
#include "thr_data.h"
 | 
			
		||||
#include "mainwindow.h"
 | 
			
		||||
#include "record_format.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +19,8 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ThrPlay::ThrPlay() {
 | 
			
		||||
ThrPlay::ThrPlay(MainWindow* mainwnd) {
 | 
			
		||||
    m_mainwnd = mainwnd;
 | 
			
		||||
    m_need_stop = false;
 | 
			
		||||
    m_need_pause = false;
 | 
			
		||||
    m_speed = 2;
 | 
			
		||||
| 
						 | 
				
			
			@ -63,151 +65,37 @@ void ThrPlay::_notify_error(const QString& msg) {
 | 
			
		|||
 | 
			
		||||
void ThrPlay::run() {
 | 
			
		||||
 | 
			
		||||
    // http://127.0.0.1:7190/tp_1491560510_ca67fceb75a78c9d/211
 | 
			
		||||
    // E:\work\tp4a\teleport\server\share\replay\rdp\000000211
 | 
			
		||||
    ThrData* thr_data = m_mainwnd->get_thr_data();
 | 
			
		||||
    bool first_run = true;
 | 
			
		||||
 | 
			
		||||
//#ifdef __APPLE__
 | 
			
		||||
//    QString currentPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
 | 
			
		||||
//    currentPath += "/tp-testdata/";
 | 
			
		||||
//#else
 | 
			
		||||
//    QString currentPath = QCoreApplication::applicationDirPath() + "/testdata/";
 | 
			
		||||
//#endif
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        if(m_need_stop)
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
    // /Users/apex/Library/Preferences/tp-player
 | 
			
		||||
//    qDebug() << "appdata:" << QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
 | 
			
		||||
 | 
			
		||||
    // /private/var/folders/_3/zggrxjdx1lxcdqnfsbgpcwzh0000gn/T
 | 
			
		||||
    //qDebug() << "tmp:" << QStandardPaths::writableLocation(QStandardPaths::TempLocation);
 | 
			
		||||
 | 
			
		||||
//    m_thr_data = new ThrData(this, m_res);
 | 
			
		||||
//    m_thr_data->start();
 | 
			
		||||
 | 
			
		||||
    // "正在准备录像数据,请稍候..."
 | 
			
		||||
//    _notify_message(LOCAL8BIT("正在准备录像数据,请稍候..."));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    // base of data path (include the .tpr file)
 | 
			
		||||
    QString path_base;
 | 
			
		||||
 | 
			
		||||
    QString _tmp_res = m_res.toLower();
 | 
			
		||||
    if(_tmp_res.startsWith("http")) {
 | 
			
		||||
        qDebug() << "DOWNLOAD";
 | 
			
		||||
        m_need_download = true;
 | 
			
		||||
 | 
			
		||||
        // "正在缓存录像数据,请稍候..."
 | 
			
		||||
        _notify_message("正在缓存录像数据,请稍候...");
 | 
			
		||||
 | 
			
		||||
        m_thr_data = new ThreadDownload(m_res);
 | 
			
		||||
        m_thr_data->start();
 | 
			
		||||
 | 
			
		||||
        QString msg;
 | 
			
		||||
        for(;;) {
 | 
			
		||||
            msleep(500);
 | 
			
		||||
 | 
			
		||||
            if(m_need_stop)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if(!m_thr_data->prepare(path_base, msg)) {
 | 
			
		||||
                msg.sprintf("指定的文件或目录不存在!\n\n%s", _tmp_res.toStdString().c_str());
 | 
			
		||||
                _notify_error(msg);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(path_base.length())
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        {
 | 
			
		||||
            QFileInfo fi(m_res);
 | 
			
		||||
            if(fi.isSymLink())
 | 
			
		||||
                _tmp_res = fi.symLinkTarget();
 | 
			
		||||
            else
 | 
			
		||||
                _tmp_res = m_res;
 | 
			
		||||
        // 1. 从ThrData的待播放队列中取出一个数据
 | 
			
		||||
        UpdateData* dat = thr_data->get_data();
 | 
			
		||||
        if(dat == nullptr) {
 | 
			
		||||
            msleep(20);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        QFileInfo fi(_tmp_res);
 | 
			
		||||
        if(!fi.exists()) {
 | 
			
		||||
            QString msg;
 | 
			
		||||
            msg.sprintf("指定的文件或目录不存在!\n\n%s", _tmp_res.toStdString().c_str());
 | 
			
		||||
            _notify_error(msg);
 | 
			
		||||
            return;
 | 
			
		||||
        if(first_run) {
 | 
			
		||||
            first_run = false;
 | 
			
		||||
           _notify_message("");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(fi.isFile()) {
 | 
			
		||||
            path_base = fi.path();
 | 
			
		||||
        // 2. 根据数据包的信息,等待到播放时间点
 | 
			
		||||
        // 3. 将数据包发送给主UI界面进行显示
 | 
			
		||||
//        qDebug("emit one package.");
 | 
			
		||||
        if(dat->data_type() == TYPE_END) {
 | 
			
		||||
            _notify_message(LOCAL8BIT("播放结束"));
 | 
			
		||||
        }
 | 
			
		||||
        else if(fi.isDir()) {
 | 
			
		||||
            path_base = m_res;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        path_base += "/";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    qint64 read_len = 0;
 | 
			
		||||
    uint32_t total_pkg = 0;
 | 
			
		||||
    uint32_t total_ms = 0;
 | 
			
		||||
    uint32_t file_count = 0;
 | 
			
		||||
 | 
			
		||||
    //======================================
 | 
			
		||||
    // 加载录像基本信息数据
 | 
			
		||||
    //======================================
 | 
			
		||||
 | 
			
		||||
    QString tpr_filename(path_base);
 | 
			
		||||
    tpr_filename += "tp-rdp.tpr";
 | 
			
		||||
 | 
			
		||||
    QFile f_hdr(tpr_filename);
 | 
			
		||||
    if(!f_hdr.open(QFile::ReadOnly)) {
 | 
			
		||||
        qDebug() << "Can not open " << tpr_filename << " for read.";
 | 
			
		||||
        QString msg;
 | 
			
		||||
        msg.sprintf("无法打开录像信息文件!\n\n%s", tpr_filename.toStdString().c_str());
 | 
			
		||||
        _notify_error(msg);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        UpdateData* dat = new UpdateData(TYPE_HEADER_INFO);
 | 
			
		||||
        dat->alloc_data(sizeof(TS_RECORD_HEADER));
 | 
			
		||||
 | 
			
		||||
        read_len = f_hdr.read((char*)(dat->data_buf()), dat->data_len());
 | 
			
		||||
        if(read_len != sizeof(TS_RECORD_HEADER)) {
 | 
			
		||||
            delete dat;
 | 
			
		||||
            qDebug() << "invaid .tpr file.";
 | 
			
		||||
            QString msg;
 | 
			
		||||
            msg.sprintf("错误的录像信息文件!\n\n%s", tpr_filename.toStdString().c_str());
 | 
			
		||||
            _notify_error(msg);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        TS_RECORD_HEADER* hdr = (TS_RECORD_HEADER*)dat->data_buf();
 | 
			
		||||
 | 
			
		||||
        if(hdr->info.ver != 4) {
 | 
			
		||||
            delete dat;
 | 
			
		||||
            qDebug() << "invaid .tpr file.";
 | 
			
		||||
            QString msg;
 | 
			
		||||
            msg.sprintf("不支持的录像文件版本 %d!\n\n此播放器支持录像文件版本 4。", hdr->info.ver);
 | 
			
		||||
            _notify_error(msg);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(hdr->basic.width == 0 || hdr->basic.height == 0) {
 | 
			
		||||
            _notify_error("错误的录像信息,未记录窗口尺寸!");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(hdr->info.dat_file_count == 0) {
 | 
			
		||||
            _notify_error("错误的录像信息,未记录数据文件数量!");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        total_pkg = hdr->info.packages;
 | 
			
		||||
        total_ms = hdr->info.time_ms;
 | 
			
		||||
        file_count = hdr->info.dat_file_count;
 | 
			
		||||
 | 
			
		||||
        emit signal_update_data(dat);
 | 
			
		||||
    }
 | 
			
		||||
        msleep(5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    //======================================
 | 
			
		||||
    // 加载录像文件数据并播放
 | 
			
		||||
    //======================================
 | 
			
		||||
| 
						 | 
				
			
			@ -351,8 +239,7 @@ void ThrPlay::run() {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    qDebug("play end.");
 | 
			
		||||
    UpdateData* _end = new UpdateData(TYPE_END);
 | 
			
		||||
    emit signal_update_data(_end);
 | 
			
		||||
//    qDebug("play end.");
 | 
			
		||||
//    UpdateData* _end = new UpdateData(TYPE_END);
 | 
			
		||||
//    emit signal_update_data(_end);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@
 | 
			
		|||
#include "update_data.h"
 | 
			
		||||
#include "downloader.h"
 | 
			
		||||
 | 
			
		||||
class MainWindow;
 | 
			
		||||
// 根据播放规则,将要播放的图像发送给主UI线程进行显示
 | 
			
		||||
class ThrPlay : public QThread
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +13,7 @@ class ThrPlay : public QThread
 | 
			
		|||
 | 
			
		||||
friend class ThrData;
 | 
			
		||||
public:
 | 
			
		||||
    ThrPlay();
 | 
			
		||||
    ThrPlay(MainWindow* mainwnd);
 | 
			
		||||
    ~ThrPlay();
 | 
			
		||||
 | 
			
		||||
    virtual void run();
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +30,7 @@ signals:
 | 
			
		|||
    void signal_update_data(UpdateData*);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    MainWindow* m_mainwnd;
 | 
			
		||||
    bool m_need_stop;
 | 
			
		||||
    bool m_need_pause;
 | 
			
		||||
    int m_speed;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,8 @@ HEADERS += \
 | 
			
		|||
    record_format.h \
 | 
			
		||||
    rle.h \
 | 
			
		||||
    util.h \
 | 
			
		||||
    downloader.h
 | 
			
		||||
    downloader.h \
 | 
			
		||||
    thr_download.h
 | 
			
		||||
 | 
			
		||||
SOURCES += \
 | 
			
		||||
    main.cpp \
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +26,8 @@ SOURCES += \
 | 
			
		|||
    update_data.cpp \
 | 
			
		||||
    rle.c \
 | 
			
		||||
    util.cpp \
 | 
			
		||||
    downloader.cpp
 | 
			
		||||
    downloader.cpp \
 | 
			
		||||
    thr_download.cpp
 | 
			
		||||
 | 
			
		||||
RESOURCES += \
 | 
			
		||||
    tp-player.qrc
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue