mirror of https://github.com/tp4a/teleport
downloader works.
parent
a7b8b68ae6
commit
5754f49f30
|
@ -5,41 +5,36 @@
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <qelapsedtimer.h>
|
#include <qelapsedtimer.h>
|
||||||
|
|
||||||
|
Downloader::Downloader() : QObject () {
|
||||||
// TODO: 将Downloader的实现代码迁移到ThrData线程中
|
m_data = nullptr;
|
||||||
// 使用局部event循环的方式进行下载
|
|
||||||
/*
|
|
||||||
QEventLoop eventLoop;
|
|
||||||
connect(netWorker, &NetWorker::finished,
|
|
||||||
&eventLoop, &QEventLoop::quit);
|
|
||||||
QNetworkReply *reply = netWorker->get(url);
|
|
||||||
replyMap.insert(reply, FetchWeatherInfo);
|
|
||||||
eventLoop.exec();
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//=================================================================
|
|
||||||
// Downloader
|
|
||||||
//=================================================================
|
|
||||||
Downloader::Downloader() {
|
|
||||||
m_reply = nullptr;
|
m_reply = nullptr;
|
||||||
m_code = codeDownloading;
|
m_result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Downloader::~Downloader() {
|
Downloader::~Downloader() {
|
||||||
// qDebug("Downloader destroied.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downloader::run(QNetworkAccessManager* nam, const QString& url, const QString& sid, const QString& filename) {
|
bool Downloader::request(const QString& url, const QString& sid, const QString& filename) {
|
||||||
m_code = codeDownloading;
|
return _request(url, sid, filename, nullptr);
|
||||||
m_filename = filename;
|
}
|
||||||
|
|
||||||
if(!m_filename.isEmpty()) {
|
bool Downloader::request(const QString& url, const QString& sid, QByteArray* data) {
|
||||||
m_file.setFileName(m_filename);
|
QString fname;
|
||||||
|
return _request(url, sid, fname, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Downloader::_request(const QString& url, const QString& sid, const QString& filename, QByteArray* data) {
|
||||||
|
if(filename.isEmpty() && data == nullptr)
|
||||||
|
return false;
|
||||||
|
if(!filename.isEmpty() && data != nullptr)
|
||||||
|
return false;
|
||||||
|
m_data = data;
|
||||||
|
|
||||||
|
if(!filename.isEmpty()) {
|
||||||
|
m_file.setFileName(filename);
|
||||||
if(!m_file.open(QIODevice::WriteOnly | QFile::Truncate)){
|
if(!m_file.open(QIODevice::WriteOnly | QFile::Truncate)){
|
||||||
qDebug("open file for write failed.");
|
qDebug("open file for write failed.");
|
||||||
m_code = codeFailed;
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,28 +44,36 @@ void Downloader::run(QNetworkAccessManager* nam, const QString& url, const QStri
|
||||||
req.setUrl(QUrl(url));
|
req.setUrl(QUrl(url));
|
||||||
req.setRawHeader("Cookie", cookie.toLatin1());
|
req.setRawHeader("Cookie", cookie.toLatin1());
|
||||||
|
|
||||||
QEventLoop eventLoop;
|
QNetworkAccessManager* nam = new QNetworkAccessManager();
|
||||||
|
QEventLoop eloop;
|
||||||
m_reply = nam->get(req);
|
m_reply = nam->get(req);
|
||||||
connect(m_reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
|
|
||||||
|
connect(m_reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
|
||||||
connect(m_reply, &QNetworkReply::finished, this, &Downloader::_on_finished);
|
connect(m_reply, &QNetworkReply::finished, this, &Downloader::_on_finished);
|
||||||
connect(m_reply, &QIODevice::readyRead, this, &Downloader::_on_data_ready);
|
connect(m_reply, &QIODevice::readyRead, this, &Downloader::_on_data_ready);
|
||||||
|
|
||||||
eventLoop.exec();
|
// qDebug("before eventLoop.exec(%p)", &eloop);
|
||||||
|
eloop.exec();
|
||||||
|
// qDebug("after eventLoop.exec()");
|
||||||
|
|
||||||
disconnect(m_reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
|
disconnect(m_reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
|
||||||
disconnect(m_reply, &QNetworkReply::finished, this, &Downloader::_on_finished);
|
disconnect(m_reply, &QNetworkReply::finished, this, &Downloader::_on_finished);
|
||||||
disconnect(m_reply, &QIODevice::readyRead, this, &Downloader::_on_data_ready);
|
disconnect(m_reply, &QIODevice::readyRead, this, &Downloader::_on_data_ready);
|
||||||
|
|
||||||
delete m_reply;
|
delete m_reply;
|
||||||
m_reply = nullptr;
|
m_reply = nullptr;
|
||||||
qDebug("Downloader::run(%p) end.", this);
|
delete nam;
|
||||||
|
|
||||||
|
qDebug("Downloader::_request() end.");
|
||||||
|
return m_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downloader::_on_data_ready() {
|
void Downloader::_on_data_ready() {
|
||||||
// qDebug("Downloader::_on_data_ready(%p).", this);
|
// qDebug("Downloader::_on_data_ready(%p).", this);
|
||||||
QNetworkReply *reply = reinterpret_cast<QNetworkReply*>(sender());
|
QNetworkReply *reply = reinterpret_cast<QNetworkReply*>(sender());
|
||||||
|
|
||||||
if(m_filename.isEmpty()) {
|
if(m_data != nullptr) {
|
||||||
m_data += reply->readAll();
|
m_data->push_back(reply->readAll());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_file.write(reply->readAll());
|
m_file.write(reply->readAll());
|
||||||
|
@ -79,9 +82,8 @@ void Downloader::_on_data_ready() {
|
||||||
|
|
||||||
void Downloader::abort() {
|
void Downloader::abort() {
|
||||||
if(m_reply) {
|
if(m_reply) {
|
||||||
qDebug("Downloader::abort(%p);", this);
|
qDebug("Downloader::abort().");
|
||||||
m_reply->abort();
|
m_reply->abort();
|
||||||
m_code = codeAbort;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,16 +96,17 @@ void Downloader::_on_finished() {
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
// reply->abort() got "Operation canceled"
|
// reply->abort() got "Operation canceled"
|
||||||
//QString strError = reply->errorString();
|
//QString strError = reply->errorString();
|
||||||
//qDebug() << strError;
|
qDebug() << "ERROR:" << reply->errorString();
|
||||||
|
if(m_data == nullptr) {
|
||||||
m_file.flush();
|
m_file.flush();
|
||||||
m_file.close();
|
m_file.close();
|
||||||
if(m_code != codeDownloading)
|
}
|
||||||
m_code = codeFailed;
|
m_result = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_filename.isEmpty()) {
|
if(m_data != nullptr) {
|
||||||
m_data += reply->readAll();
|
m_data->push_back(reply->readAll());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_file.write(reply->readAll());
|
m_file.write(reply->readAll());
|
||||||
|
@ -113,5 +116,5 @@ void Downloader::_on_finished() {
|
||||||
|
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
m_code = codeSuccess;
|
m_result = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,37 +8,27 @@ class Downloader : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum EndCode{
|
// 从url下载数据,写入到filename文件中,或放入data中。
|
||||||
codeSuccess,
|
|
||||||
codeDownloading,
|
|
||||||
codeAbort,
|
|
||||||
codeFailed
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// 从url下载数据,写入到filename文件中,如果filename为空字符串,则保存在内存中,可通过 data() 获取。
|
|
||||||
Downloader();
|
Downloader();
|
||||||
~Downloader();
|
~Downloader();
|
||||||
|
|
||||||
void run(QNetworkAccessManager* nam, const QString& url, const QString& sid, const QString& filename);
|
bool request(const QString& url, const QString& sid, const QString& filename);
|
||||||
|
bool request(const QString& url, const QString& sid, QByteArray* data);
|
||||||
void abort();
|
void abort();
|
||||||
// void reset();
|
|
||||||
QByteArray& data(){return m_data;}
|
|
||||||
|
|
||||||
EndCode code() {return m_code;}
|
private:
|
||||||
|
bool _request(const QString& url, const QString& sid, const QString& filename, QByteArray* data);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void _on_data_ready(); // 有数据可读了,读取并写入文件
|
void _on_data_ready(); // 有数据可读了,读取并写入文件
|
||||||
void _on_finished(); // 下载结束了
|
void _on_finished(); // 下载结束了
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_filename;
|
|
||||||
QFile m_file;
|
QFile m_file;
|
||||||
QByteArray m_data;
|
QByteArray* m_data;
|
||||||
|
|
||||||
|
bool m_result;
|
||||||
QNetworkReply* m_reply;
|
QNetworkReply* m_reply;
|
||||||
|
|
||||||
EndCode m_code;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct DownloadParam {
|
typedef struct DownloadParam {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "thr_play.h"
|
#include "thr_play.h"
|
||||||
#include "thr_data.h"
|
#include "thr_data.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "downloader.h"
|
||||||
#include "record_format.h"
|
#include "record_format.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ ThrData::ThrData(MainWindow* mainwin, const QString& res) {
|
||||||
m_res = res;
|
m_res = res;
|
||||||
m_need_download = false;
|
m_need_download = false;
|
||||||
m_need_stop = false;
|
m_need_stop = false;
|
||||||
m_dl = nullptr;
|
// m_dl = nullptr;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
QString data_path_base = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
QString data_path_base = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
|
@ -49,19 +50,12 @@ GenericCacheLocation: "C:/Users/apex/AppData/Local/cache"
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrData::~ThrData() {
|
ThrData::~ThrData() {
|
||||||
if(m_dl)
|
|
||||||
delete m_dl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThrData::stop() {
|
void ThrData::stop() {
|
||||||
if(!isRunning())
|
if(!isRunning())
|
||||||
return;
|
return;
|
||||||
m_need_stop = true;
|
m_need_stop = true;
|
||||||
|
|
||||||
if(m_dl) {
|
|
||||||
m_dl->abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
wait();
|
wait();
|
||||||
qDebug("data thread stop() end.");
|
qDebug("data thread stop() end.");
|
||||||
}
|
}
|
||||||
|
@ -82,19 +76,137 @@ void ThrData::_notify_error(const QString& msg) {
|
||||||
// TP服务器地址(可能包含子路径哦,例如上例中的{sub/path/}部分)/session-id(用于判断当前授权用户)/录像会话编号
|
// TP服务器地址(可能包含子路径哦,例如上例中的{sub/path/}部分)/session-id(用于判断当前授权用户)/录像会话编号
|
||||||
|
|
||||||
void ThrData::run() {
|
void ThrData::run() {
|
||||||
|
_run();
|
||||||
|
qDebug("ThrData thread run() end.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThrData::_run() {
|
||||||
if(!_load_header())
|
if(!_load_header())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!_load_keyframe())
|
if(!_load_keyframe())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// for(;;) {
|
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_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 filesize = f_tpd.size();
|
||||||
|
qint64 processed = 0;
|
||||||
|
|
||||||
|
// 加载并解析到待播放队列
|
||||||
|
qint64 read_len = 0;
|
||||||
|
for(;;) {
|
||||||
|
{
|
||||||
// if(m_need_stop)
|
// if(m_need_stop)
|
||||||
// break;
|
// break;
|
||||||
// msleep(500);
|
|
||||||
|
// m_locker.lock();
|
||||||
|
|
||||||
|
// if(m_data.size() > 500) {
|
||||||
|
// msleep(1000);
|
||||||
|
// continue;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
qDebug("ThrData thread run() end.");
|
// m_locker.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TS_RECORD_PKG pkg;
|
||||||
|
read_len = f_tpd.read(reinterpret_cast<char*>(&pkg), sizeof(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));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
processed += sizeof(TS_RECORD_PKG);
|
||||||
|
|
||||||
|
if(filesize - 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));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
m_locker.lock();
|
||||||
|
m_data.enqueue(dat);
|
||||||
|
// qDebug("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() {
|
bool ThrData::_load_header() {
|
||||||
|
@ -121,42 +233,11 @@ bool ThrData::_load_header() {
|
||||||
qDebug() << "url-base:[" << m_url_base << "], sid:[" << m_sid << "], rid:[" << m_rid << "]";
|
qDebug() << "url-base:[" << m_url_base << "], sid:[" << m_sid << "], rid:[" << m_rid << "]";
|
||||||
|
|
||||||
// download .tpr
|
// download .tpr
|
||||||
QString url(m_url_base);
|
QString url = QString("%1/audit/get-file?act=read&type=rdp&rid=%2&f=tp-rdp.tpr").arg(m_url_base, m_rid);
|
||||||
url += "/audit/get-file?act=read&type=rdp&rid=";
|
QByteArray data;
|
||||||
url += m_rid;
|
if(!_download_file(url, data))
|
||||||
url += "&f=tp-rdp.tpr";
|
|
||||||
|
|
||||||
QString fname;
|
|
||||||
if(!_download_file(url, fname))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Downloader& dl = m_mainwin->downloader();
|
|
||||||
// dl.reset();
|
|
||||||
|
|
||||||
// DownloadParam param;
|
|
||||||
// param.url = url;
|
|
||||||
// param.sid = m_sid;
|
|
||||||
// param.fname = fname;
|
|
||||||
// _notify_download(¶m);
|
|
||||||
|
|
||||||
// for(;;) {
|
|
||||||
// if(dl.code() == Downloader::codeUnknown || dl.code() == Downloader::codeDownloading) {
|
|
||||||
// msleep(100);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if(dl.code() != Downloader::codeSuccess) {
|
|
||||||
// _notify_error(QString("%1").arg(LOCAL8BIT("下载文件失败!")));
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//Downloader* dl = m_mainwin->downloader();
|
|
||||||
if(!m_dl)
|
|
||||||
return false;
|
|
||||||
QByteArray& data = m_dl->data();
|
|
||||||
if(data.size() != sizeof(TS_RECORD_HEADER)) {
|
if(data.size() != sizeof(TS_RECORD_HEADER)) {
|
||||||
qDebug("invalid header file. %d", data.size());
|
qDebug("invalid header file. %d", data.size());
|
||||||
_notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("指定的文件或目录不存在!"), _tmp_res));
|
_notify_error(QString("%1\n\n%2").arg(LOCAL8BIT("指定的文件或目录不存在!"), _tmp_res));
|
||||||
|
@ -305,12 +386,8 @@ bool ThrData::_load_keyframe() {
|
||||||
|
|
||||||
QFileInfo fi_tpk(tpk_fname);
|
QFileInfo fi_tpk(tpk_fname);
|
||||||
if(!fi_tpk.exists()) {
|
if(!fi_tpk.exists()) {
|
||||||
QString url(m_url_base);
|
QString url = QString("%1/audit/get-file?act=read&type=rdp&rid=%2&f=tp-rdp.tpk").arg(m_url_base, m_rid);
|
||||||
url += "/audit/get-file?act=read&type=rdp&rid=";
|
qDebug() << "TPK: " << tmp_fname;
|
||||||
url += m_rid;
|
|
||||||
url += "&f=tp-rdp.tpk";
|
|
||||||
|
|
||||||
qDebug() << "TPK(tmp): " << tmp_fname;
|
|
||||||
if(!_download_file(url, tmp_fname))
|
if(!_download_file(url, tmp_fname))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -359,349 +436,34 @@ bool ThrData::_download_file(const QString& url, const QString filename) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_dl) {
|
Downloader dl;
|
||||||
delete m_dl;
|
if(!dl.request(url, m_sid, filename)) {
|
||||||
m_dl = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dl = new Downloader();
|
|
||||||
|
|
||||||
QNetworkAccessManager* nam = new QNetworkAccessManager;
|
|
||||||
|
|
||||||
m_dl->run(nam, url, m_sid, filename);
|
|
||||||
// qDebug("m_dl.run(%p) end.", m_dl);
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
if(m_dl->code() == Downloader::codeDownloading) {
|
|
||||||
msleep(100);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_dl->code() != Downloader::codeSuccess) {
|
|
||||||
qDebug() << "download failed.";
|
qDebug() << "download failed.";
|
||||||
_notify_error(QString("%1").arg(LOCAL8BIT("下载文件失败!")));
|
_notify_error(QString("%1").arg(LOCAL8BIT("下载文件失败!")));
|
||||||
delete nam;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
qDebug() << "download ok.";
|
|
||||||
delete nam;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
bool ThrData::_download_file(const QString& url, QByteArray& data) {
|
||||||
bool ThrData::_download_file(const QString& url, const QString filename) {
|
|
||||||
if(!m_need_download) {
|
if(!m_need_download) {
|
||||||
qDebug() << "download not necessary.";
|
qDebug() << "download not necessary.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_mainwin->reset_downloader();
|
Downloader dl;
|
||||||
msleep(100);
|
|
||||||
|
|
||||||
DownloadParam param;
|
if(!dl.request(url, m_sid, &data)) {
|
||||||
param.url = url;
|
|
||||||
param.sid = m_sid;
|
|
||||||
param.fname = filename;
|
|
||||||
_notify_download(¶m);
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
Downloader* dl = m_mainwin->downloader();
|
|
||||||
if(!dl || dl->code() == Downloader::codeUnknown || dl->code() == Downloader::codeDownloading) {
|
|
||||||
msleep(100);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dl->code() != Downloader::codeSuccess) {
|
|
||||||
qDebug() << "download failed.";
|
qDebug() << "download failed.";
|
||||||
_notify_error(QString("%1").arg(LOCAL8BIT("下载文件失败!")));
|
_notify_error(QString("%1").arg(LOCAL8BIT("下载文件失败!")));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
qDebug() << "download ok.";
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void ThrData::run() {
|
|
||||||
QString msg;
|
|
||||||
QString path_base;
|
|
||||||
|
|
||||||
QString _tmp_res = m_res.toLower();
|
|
||||||
|
|
||||||
if(_tmp_res.startsWith("http")) {
|
|
||||||
qDebug() << "DOWNLOAD";
|
|
||||||
m_need_download = true;
|
|
||||||
|
|
||||||
// "正在缓存录像数据,请稍候..."
|
|
||||||
m_thr_play->_notify_message(LOCAL8BIT("正在下载录像数据,请稍候..."));
|
|
||||||
|
|
||||||
// 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_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()) {
|
|
||||||
msg.sprintf(LOCAL8BIT("指定的文件或目录不存在!\n\n%s").toStdString().c_str(), _tmp_res.toStdString().c_str());
|
|
||||||
m_thr_play->_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fi.isFile()) {
|
|
||||||
path_base = fi.path();
|
|
||||||
}
|
|
||||||
else if(fi.isDir()) {
|
|
||||||
path_base = m_res;
|
|
||||||
}
|
|
||||||
|
|
||||||
path_base += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
//======================================
|
|
||||||
// 加载录像基本信息数据
|
|
||||||
//======================================
|
|
||||||
|
|
||||||
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.";
|
|
||||||
msg.sprintf(LOCAL8BIT("无法打开录像信息文件!\n\n%s").toStdString().c_str(), tpr_filename.toStdString().c_str());
|
|
||||||
m_thr_play->_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TS_RECORD_HEADER hdr;
|
|
||||||
memset(&hdr, 0, sizeof(TS_RECORD_HEADER));
|
|
||||||
|
|
||||||
qint64 read_len = 0;
|
|
||||||
read_len = f_hdr.read((char*)(&hdr), sizeof(TS_RECORD_HEADER));
|
|
||||||
if(read_len != sizeof(TS_RECORD_HEADER)) {
|
|
||||||
qDebug() << "invaid .tpr file.";
|
|
||||||
msg.sprintf(LOCAL8BIT("错误的录像信息文件!\n\n%s").toStdString().c_str(), tpr_filename.toStdString().c_str());
|
|
||||||
m_thr_play->_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hdr.info.ver != 4) {
|
|
||||||
qDebug() << "invaid .tpr file.";
|
|
||||||
msg.sprintf(LOCAL8BIT("不支持的录像文件版本 %d!\n\n此播放器支持录像文件版本 4。").toStdString().c_str(), hdr.info.ver);
|
|
||||||
m_thr_play->_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hdr.basic.width == 0 || hdr.basic.height == 0) {
|
|
||||||
m_thr_play->_notify_error(LOCAL8BIT("错误的录像信息,未记录窗口尺寸!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hdr.info.dat_file_count == 0) {
|
|
||||||
m_thr_play->_notify_error(LOCAL8BIT("错误的录像信息,未记录数据文件数量!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//======================================
|
|
||||||
// 加载关键帧数据
|
|
||||||
//======================================
|
|
||||||
QString tpk_filename(path_base);
|
|
||||||
tpk_filename += "tp-rdp.tpk";
|
|
||||||
|
|
||||||
QFile f_kf(tpk_filename);
|
|
||||||
if(!f_kf.open(QFile::ReadOnly)) {
|
|
||||||
qDebug() << "Can not open " << tpk_filename << " for read.";
|
|
||||||
msg.sprintf(LOCAL8BIT("无法打开关键帧信息文件!\n\n%s").toStdString().c_str(), tpk_filename.toStdString().c_str());
|
|
||||||
m_thr_play->_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 fsize = f_kf.size();
|
|
||||||
if(!fsize || fsize % sizeof(KEYFRAME_INFO) != 0) {
|
|
||||||
qDebug() << "Can not open " << tpk_filename << " for read.";
|
|
||||||
msg.sprintf(LOCAL8BIT("关键帧信息文件格式错误!\n\n").toStdString().c_str());
|
|
||||||
m_thr_play->_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kf_count = fsize / sizeof(KEYFRAME_INFO);
|
|
||||||
for(int i = 0; i < kf_count; ++i) {
|
|
||||||
KEYFRAME_INFO kf;
|
|
||||||
memset(&kf, 0, sizeof(KEYFRAME_INFO));
|
|
||||||
read_len = f_kf.read((char*)(&kf), sizeof(KEYFRAME_INFO));
|
|
||||||
if(read_len != sizeof(KEYFRAME_INFO)) {
|
|
||||||
qDebug() << "invaid .tpk file.";
|
|
||||||
msg.sprintf(LOCAL8BIT("关键帧信息文件格式错误!\n\n").toStdString().c_str());
|
|
||||||
m_thr_play->_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_kf.push_back(kf);
|
|
||||||
}
|
|
||||||
|
|
||||||
//======================================
|
|
||||||
// 读取并解析录像数据文件
|
|
||||||
//======================================
|
|
||||||
uint32_t fidx = 0;
|
|
||||||
while(!m_need_stop) {
|
|
||||||
|
|
||||||
for(fidx = 0; fidx < hdr.info.dat_file_count; ++fidx) {
|
|
||||||
QString tpd_filename(path_base);
|
|
||||||
QString str_tmp;
|
|
||||||
|
|
||||||
str_tmp.sprintf("tp-rdp-%d.tpd", fidx+1);
|
|
||||||
tpd_filename += str_tmp;
|
|
||||||
|
|
||||||
QFileInfo fi(tpd_filename);
|
|
||||||
if(!fi.isFile()) {
|
|
||||||
// 文件不存在,如需下载,则启动下载函数并等待下载结束。(下载是异步的吗?)
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile f_dat(tpd_filename);
|
|
||||||
if(!f_dat.open(QFile::ReadOnly)) {
|
|
||||||
qDebug() << "Can not open " << tpd_filename << " for read.";
|
|
||||||
// msg.sprintf("无法打开录像数据文件!\n\n%s", tpd_filename.toStdString().c_str());
|
|
||||||
msg = QString::fromLocal8Bit("无法打开录像数据文件!\n\n");
|
|
||||||
msg += tpd_filename;
|
|
||||||
m_thr_play->_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
if(m_need_stop) {
|
|
||||||
qDebug() << "stop, user cancel 2.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_need_pause) {
|
|
||||||
msleep(50);
|
|
||||||
time_begin += 50;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TS_RECORD_PKG pkg;
|
|
||||||
read_len = f_dat.read((char*)(&pkg), sizeof(pkg));
|
|
||||||
if(read_len == 0)
|
|
||||||
break;
|
|
||||||
if(read_len != sizeof(TS_RECORD_PKG)) {
|
|
||||||
qDebug() << "invaid .tpd file (1).";
|
|
||||||
// msg.sprintf("错误的录像数据文件!\n\n%s", tpd_filename.toStdString().c_str());
|
|
||||||
msg = QString::fromLocal8Bit("错误的录像数据文件!\n\n");
|
|
||||||
msg += tpd_filename.toStdString().c_str();
|
|
||||||
_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
|
|
||||||
qDebug("----key frame: %d", pkg.time_ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_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());
|
|
||||||
msg = QString::fromLocal8Bit("错误的录像数据文件!\n\n");
|
|
||||||
msg += tpd_filename.toStdString().c_str();
|
|
||||||
_notify_error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg_count++;
|
|
||||||
|
|
||||||
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) {
|
|
||||||
UpdateData* _passed_ms = new UpdateData(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(;;) {
|
|
||||||
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) {
|
|
||||||
UpdateData* _passed_ms = new UpdateData(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// msg = LOCAL8BIT("开始播放...");
|
|
||||||
// m_thr_play->_notify_error(msg);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ThrData::_prepare() {
|
void ThrData::_prepare() {
|
||||||
UpdateData* d = new UpdateData(TYPE_HEADER_INFO);
|
UpdateData* d = new UpdateData(TYPE_HEADER_INFO);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include "downloader.h"
|
#include <QEventLoop>
|
||||||
#include "update_data.h"
|
#include "update_data.h"
|
||||||
#include "record_format.h"
|
#include "record_format.h"
|
||||||
|
|
||||||
|
@ -59,16 +59,17 @@ public:
|
||||||
UpdateData* get_data();
|
UpdateData* get_data();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _run();
|
||||||
|
|
||||||
bool _load_header();
|
bool _load_header();
|
||||||
bool _load_keyframe();
|
bool _load_keyframe();
|
||||||
bool _download_file(const QString& url, const QString filename);
|
bool _download_file(const QString& url, const QString filename);
|
||||||
|
bool _download_file(const QString& url, QByteArray& data);
|
||||||
|
|
||||||
void _prepare();
|
void _prepare();
|
||||||
|
|
||||||
void _notify_message(const QString& msg);
|
void _notify_message(const QString& msg);
|
||||||
void _notify_error(const QString& err_msg);
|
void _notify_error(const QString& err_msg);
|
||||||
void _notify_download(DownloadParam* param);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void signal_update_data(UpdateData*);
|
void signal_update_data(UpdateData*);
|
||||||
|
@ -89,8 +90,6 @@ private:
|
||||||
QString m_rid;
|
QString m_rid;
|
||||||
QString m_path_base;
|
QString m_path_base;
|
||||||
|
|
||||||
Downloader* m_dl;
|
|
||||||
|
|
||||||
TS_RECORD_HEADER m_hdr;
|
TS_RECORD_HEADER m_hdr;
|
||||||
KeyFrames m_kf;
|
KeyFrames m_kf;
|
||||||
};
|
};
|
||||||
|
|
|
@ -711,8 +711,8 @@ class DoGetFileHandler(TPBaseHandler):
|
||||||
self.set_status(416) # 416=请求范围不符合要求
|
self.set_status(416) # 416=请求范围不符合要求
|
||||||
return self.write('no more data.')
|
return self.write('no more data.')
|
||||||
|
|
||||||
# we read most 4096 bytes one time.
|
# we read most 8192 bytes one time.
|
||||||
BULK_SIZE = 4096
|
BULK_SIZE = 8192
|
||||||
total_need = file_size - offset
|
total_need = file_size - offset
|
||||||
if length != -1 and length < total_need:
|
if length != -1 and length < total_need:
|
||||||
total_need = length
|
total_need = length
|
||||||
|
@ -722,6 +722,7 @@ class DoGetFileHandler(TPBaseHandler):
|
||||||
read_this_time = BULK_SIZE if total_need > BULK_SIZE else total_need
|
read_this_time = BULK_SIZE if total_need > BULK_SIZE else total_need
|
||||||
while read_this_time > 0:
|
while read_this_time > 0:
|
||||||
self.write(f.read(read_this_time))
|
self.write(f.read(read_this_time))
|
||||||
|
self.flush()
|
||||||
total_read += read_this_time
|
total_read += read_this_time
|
||||||
if total_read >= total_need:
|
if total_read >= total_need:
|
||||||
break
|
break
|
||||||
|
|
Loading…
Reference in New Issue