2019-09-09 18:39:08 +00:00
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
#include <QDateTime>
|
2019-09-04 20:21:29 +00:00
|
|
|
|
#include <QDebug>
|
2019-09-02 21:40:52 +00:00
|
|
|
|
|
|
|
|
|
#include "thr_play.h"
|
2019-10-31 17:45:17 +00:00
|
|
|
|
#include "thr_data.h"
|
2019-11-03 19:34:11 +00:00
|
|
|
|
#include "mainwindow.h"
|
2019-09-02 21:40:52 +00:00
|
|
|
|
#include "record_format.h"
|
2019-10-31 17:45:17 +00:00
|
|
|
|
#include "util.h"
|
2019-09-02 21:40:52 +00:00
|
|
|
|
|
2019-10-31 17:45:17 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 录像播放流程:
|
|
|
|
|
* - 数据处理线程,该线程负责(下载)文件、解析文件,将数据准备成待播放队列;
|
|
|
|
|
* + 数据处理线程维护待播放队列,少于500个则填充至1000个,每20ms检查一次队列是否少于500个。
|
|
|
|
|
* - 播放线程从队列中取出一个数据,判断当前时间是否应该播放此数据,如果应该,则将此数据发送给主UI
|
|
|
|
|
* + if( 播放速率 * (当前时间 - 播放时间) >= (当前数据包偏移时间 - 上个数据包偏移时间)) 则 播放
|
|
|
|
|
* + 如选择“跳过无操作时间”,则数据包偏移时间差超过3秒的,视为3秒。
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2019-11-03 19:34:11 +00:00
|
|
|
|
ThrPlay::ThrPlay(MainWindow* mainwnd) {
|
|
|
|
|
m_mainwnd = mainwnd;
|
2019-09-02 21:40:52 +00:00
|
|
|
|
m_need_stop = false;
|
2019-09-09 18:04:23 +00:00
|
|
|
|
m_need_pause = false;
|
2019-11-04 19:05:29 +00:00
|
|
|
|
m_speed = 1;
|
|
|
|
|
m_skip = false;
|
2019-11-05 18:49:30 +00:00
|
|
|
|
m_start_ms = 0;
|
2019-09-16 05:53:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 17:45:17 +00:00
|
|
|
|
ThrPlay::~ThrPlay() {
|
2019-09-16 05:53:27 +00:00
|
|
|
|
stop();
|
2019-09-02 21:40:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 17:45:17 +00:00
|
|
|
|
void ThrPlay::stop() {
|
2019-09-16 05:53:27 +00:00
|
|
|
|
if(!isRunning())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// warning: never call stop() inside thread::run() loop.
|
|
|
|
|
|
2019-09-02 21:40:52 +00:00
|
|
|
|
m_need_stop = true;
|
2019-09-16 05:53:27 +00:00
|
|
|
|
wait();
|
|
|
|
|
qDebug() << "play-thread end.";
|
|
|
|
|
|
2019-10-31 17:45:17 +00:00
|
|
|
|
// if(m_thr_data) {
|
|
|
|
|
// m_thr_data->stop();
|
|
|
|
|
// qDebug("delete thrData.");
|
|
|
|
|
// //m_thr_download->wait();
|
|
|
|
|
// delete m_thr_data;
|
|
|
|
|
// m_thr_data = nullptr;
|
|
|
|
|
// }
|
2019-09-02 21:40:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 17:45:17 +00:00
|
|
|
|
void ThrPlay::_notify_message(const QString& msg) {
|
|
|
|
|
UpdateData* _msg = new UpdateData(TYPE_MESSAGE);
|
2019-09-16 05:53:27 +00:00
|
|
|
|
_msg->message(msg);
|
|
|
|
|
emit signal_update_data(_msg);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 17:45:17 +00:00
|
|
|
|
void ThrPlay::_notify_error(const QString& msg) {
|
|
|
|
|
UpdateData* _msg = new UpdateData(TYPE_ERROR);
|
|
|
|
|
_msg->message(msg);
|
|
|
|
|
emit signal_update_data(_msg);
|
2019-09-16 05:53:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 18:49:30 +00:00
|
|
|
|
void ThrPlay::resume(bool relocate, uint32_t start_ms) {
|
|
|
|
|
if(relocate) {
|
|
|
|
|
m_start_ms = start_ms;
|
|
|
|
|
m_first_run = true;
|
|
|
|
|
}
|
|
|
|
|
m_need_pause = false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 17:45:17 +00:00
|
|
|
|
void ThrPlay::run() {
|
2019-09-16 05:53:27 +00:00
|
|
|
|
|
2019-11-03 19:34:11 +00:00
|
|
|
|
ThrData* thr_data = m_mainwnd->get_thr_data();
|
2019-11-05 18:49:30 +00:00
|
|
|
|
m_first_run = true;
|
2019-11-04 19:05:29 +00:00
|
|
|
|
uint32_t last_time_ms = 0;
|
|
|
|
|
uint32_t last_pass_ms = 0;
|
2019-09-08 19:30:31 +00:00
|
|
|
|
|
2019-11-04 19:05:29 +00:00
|
|
|
|
UpdateData* dat = nullptr;
|
2019-11-03 19:34:11 +00:00
|
|
|
|
for(;;) {
|
|
|
|
|
if(m_need_stop)
|
|
|
|
|
break;
|
2019-09-16 05:53:27 +00:00
|
|
|
|
|
2019-11-03 19:34:11 +00:00
|
|
|
|
// 1. 从ThrData的待播放队列中取出一个数据
|
2019-11-04 19:05:29 +00:00
|
|
|
|
dat = thr_data->get_data();
|
2019-11-03 19:34:11 +00:00
|
|
|
|
if(dat == nullptr) {
|
|
|
|
|
msleep(20);
|
|
|
|
|
continue;
|
2019-09-16 05:53:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 18:49:30 +00:00
|
|
|
|
if(m_first_run) {
|
|
|
|
|
m_first_run = false;
|
2019-11-03 19:34:11 +00:00
|
|
|
|
_notify_message("");
|
2019-09-17 16:51:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 18:49:30 +00:00
|
|
|
|
if(m_start_ms > 0) {
|
|
|
|
|
if(dat->get_time() < m_start_ms) {
|
|
|
|
|
emit signal_update_data(dat);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
last_time_ms = m_start_ms;
|
|
|
|
|
m_start_ms = 0;
|
2019-11-10 12:37:09 +00:00
|
|
|
|
UpdateData* _enable = new UpdateData(TYPE_ENABLE_DRAW);
|
|
|
|
|
emit signal_update_data(_enable);
|
2019-11-05 18:49:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-03 19:34:11 +00:00
|
|
|
|
// 2. 根据数据包的信息,等待到播放时间点
|
2019-11-04 19:05:29 +00:00
|
|
|
|
uint32_t need_wait_ms = 0;
|
|
|
|
|
uint32_t this_time_ms = dat->get_time();
|
|
|
|
|
uint32_t this_pass_ms = last_time_ms;
|
|
|
|
|
if(this_time_ms > 0) {
|
2019-11-05 19:15:23 +00:00
|
|
|
|
if(this_time_ms >= last_time_ms)
|
|
|
|
|
need_wait_ms = this_time_ms - last_time_ms;
|
|
|
|
|
else
|
|
|
|
|
need_wait_ms = 0;
|
2019-11-04 19:05:29 +00:00
|
|
|
|
|
|
|
|
|
if(need_wait_ms > 0) {
|
|
|
|
|
uint32_t time_wait = 0;
|
|
|
|
|
|
|
|
|
|
// 如果设置了跳过无操作区间,将超过1秒的等待时间压缩至1秒。
|
|
|
|
|
if(m_skip) {
|
|
|
|
|
if(need_wait_ms > 1000)
|
|
|
|
|
need_wait_ms = 1000;
|
2019-09-17 16:51:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-04 19:05:29 +00:00
|
|
|
|
for(;;) {
|
|
|
|
|
time_wait = need_wait_ms > 10 ? 10 : need_wait_ms;
|
|
|
|
|
msleep(time_wait);
|
|
|
|
|
|
|
|
|
|
if(m_need_pause) {
|
|
|
|
|
while(m_need_pause) {
|
|
|
|
|
msleep(50);
|
|
|
|
|
if(m_need_stop)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(m_need_stop)
|
|
|
|
|
break;
|
|
|
|
|
|
2019-11-05 18:49:30 +00:00
|
|
|
|
if(m_start_ms > 0) {
|
2019-11-10 12:37:09 +00:00
|
|
|
|
delete dat;
|
|
|
|
|
dat = nullptr;
|
|
|
|
|
UpdateData* _disable = new UpdateData(TYPE_DISABLE_DRAW);
|
|
|
|
|
emit signal_update_data(_disable);
|
2019-11-05 18:49:30 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-04 19:05:29 +00:00
|
|
|
|
time_wait *= m_speed;
|
|
|
|
|
|
|
|
|
|
// 如果已经在等待长时间无操作区间内,用户设置了跳过无操作区间,则将超过0.5秒的等待时间压缩至0.5秒。
|
|
|
|
|
if(m_skip) {
|
|
|
|
|
if(need_wait_ms > 500)
|
|
|
|
|
need_wait_ms = 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this_pass_ms += time_wait;
|
|
|
|
|
if(this_pass_ms - last_pass_ms > 100) {
|
|
|
|
|
UpdateData* _passed_ms = new UpdateData(TYPE_PLAYED_MS);
|
|
|
|
|
_passed_ms->played_ms(this_pass_ms);
|
|
|
|
|
emit signal_update_data(_passed_ms);
|
|
|
|
|
last_pass_ms = this_pass_ms;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(need_wait_ms <= time_wait)
|
|
|
|
|
break;
|
|
|
|
|
else
|
|
|
|
|
need_wait_ms -= time_wait;
|
2019-09-17 16:51:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-04 19:05:29 +00:00
|
|
|
|
if(m_need_stop)
|
2019-09-17 16:51:22 +00:00
|
|
|
|
break;
|
2019-09-04 20:21:29 +00:00
|
|
|
|
}
|
2019-09-17 16:51:22 +00:00
|
|
|
|
|
2019-11-04 19:05:29 +00:00
|
|
|
|
}
|
2019-11-05 19:15:23 +00:00
|
|
|
|
last_time_ms = this_time_ms;
|
2019-11-04 19:05:29 +00:00
|
|
|
|
|
|
|
|
|
// 3. 将数据包发送给主UI界面进行显示
|
2019-11-10 12:37:09 +00:00
|
|
|
|
if(dat != nullptr) {
|
|
|
|
|
if(dat->data_type() == TYPE_END) {
|
|
|
|
|
_notify_message(LOCAL8BIT("播放结束"));
|
|
|
|
|
}
|
|
|
|
|
emit signal_update_data(dat);
|
2019-09-04 20:21:29 +00:00
|
|
|
|
}
|
2019-09-17 16:51:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-04 19:05:29 +00:00
|
|
|
|
if(dat != nullptr)
|
|
|
|
|
delete dat;
|
2019-09-02 21:40:52 +00:00
|
|
|
|
}
|