mirror of https://github.com/tp4a/teleport
播放器进度条任意拖动可以工作了。需要改进录像的关键帧处理。
parent
1bbc109ae9
commit
bde794d253
|
@ -86,6 +86,10 @@ Bar::Bar() {
|
||||||
m_speed_hover = speed_count; // speed_count=no-hover
|
m_speed_hover = speed_count; // speed_count=no-hover
|
||||||
m_skip_selected = false;
|
m_skip_selected = false;
|
||||||
m_skip_hover = false;
|
m_skip_hover = false;
|
||||||
|
m_progress_hover = false;
|
||||||
|
m_progress_pressed = false;
|
||||||
|
|
||||||
|
m_resume_ms = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bar::~Bar() {
|
Bar::~Bar() {
|
||||||
|
@ -138,7 +142,7 @@ void Bar::start(uint32_t total_ms, int width) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bar::end() {
|
void Bar::end() {
|
||||||
if(m_passed_ms != m_total_ms)
|
if(m_played_ms != m_total_ms)
|
||||||
update_passed_time(m_total_ms);
|
update_passed_time(m_total_ms);
|
||||||
|
|
||||||
m_playing = false;
|
m_playing = false;
|
||||||
|
@ -342,13 +346,14 @@ void Bar::update_passed_time(uint32_t ms) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int percent = 0;
|
int percent = 0;
|
||||||
if(ms > m_total_ms) {
|
if(ms >= m_total_ms) {
|
||||||
percent = 100;
|
percent = 100;
|
||||||
m_passed_ms = m_total_ms;
|
m_played_ms = m_total_ms;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_passed_ms = ms;
|
m_played_ms = ms;
|
||||||
percent = (int)(((double)m_passed_ms / (double)m_total_ms) * 100);
|
//percent = (int)(((double)m_played_ms / (double)m_total_ms) * 100);
|
||||||
|
percent = m_played_ms * 100 / m_total_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(percent != m_percent) {
|
if(percent != m_percent) {
|
||||||
|
@ -361,6 +366,27 @@ void Bar::onMouseMove(int x, int y) {
|
||||||
// 映射鼠标坐标点到本浮动窗内部的相对位置
|
// 映射鼠标坐标点到本浮动窗内部的相对位置
|
||||||
QPoint pt(x-m_rc.left(), y-m_rc.top());
|
QPoint pt(x-m_rc.left(), y-m_rc.top());
|
||||||
|
|
||||||
|
if(m_progress_pressed) {
|
||||||
|
// 重新设置进度条指示器位置
|
||||||
|
int percent = 0;
|
||||||
|
|
||||||
|
if(pt.x() < m_rc_progress.left()) {
|
||||||
|
percent = 0;
|
||||||
|
m_resume_ms = 0;
|
||||||
|
}
|
||||||
|
else if(pt.x() > m_rc_progress.right()) {
|
||||||
|
percent = 100;
|
||||||
|
m_resume_ms = m_total_ms;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
percent = (pt.x() + m_img_progress_pointer[widget_normal].width()/2 - m_rc_progress.left()) * 100 / m_rc_progress.width();
|
||||||
|
m_resume_ms = m_total_ms * percent / 100;
|
||||||
|
}
|
||||||
|
update_passed_time(m_resume_ms);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool play_hover = m_rc_btn_play.contains(pt);
|
bool play_hover = m_rc_btn_play.contains(pt);
|
||||||
if(play_hover != m_play_hover) {
|
if(play_hover != m_play_hover) {
|
||||||
m_play_hover = play_hover;
|
m_play_hover = play_hover;
|
||||||
|
@ -393,11 +419,13 @@ void Bar::onMouseMove(int x, int y) {
|
||||||
}
|
}
|
||||||
if(skip_hover)
|
if(skip_hover)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: more hover detect.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bar::onMousePress(int x, int y) {
|
void Bar::onMousePress(int x, int y, Qt::MouseButton button) {
|
||||||
|
// 我们只关心左键按下
|
||||||
|
if(button != Qt::LeftButton)
|
||||||
|
return;
|
||||||
|
|
||||||
// 映射鼠标坐标点到本浮动窗内部的相对位置
|
// 映射鼠标坐标点到本浮动窗内部的相对位置
|
||||||
QPoint pt(x-m_rc.left(), y-m_rc.top());
|
QPoint pt(x-m_rc.left(), y-m_rc.top());
|
||||||
|
|
||||||
|
@ -405,7 +433,7 @@ void Bar::onMousePress(int x, int y) {
|
||||||
if(m_playing)
|
if(m_playing)
|
||||||
m_owner->pause();
|
m_owner->pause();
|
||||||
else
|
else
|
||||||
m_owner->resume();
|
m_owner->resume(false, 0);
|
||||||
|
|
||||||
m_playing = !m_playing;
|
m_playing = !m_playing;
|
||||||
m_owner->update(m_rc.left()+m_rc_btn_play.left(), m_rc.top()+m_rc_btn_play.top(), m_rc_btn_play.width(), m_rc_btn_play.height());
|
m_owner->update(m_rc.left()+m_rc_btn_play.left(), m_rc.top()+m_rc_btn_play.top(), m_rc_btn_play.width(), m_rc_btn_play.height());
|
||||||
|
@ -431,9 +459,29 @@ void Bar::onMousePress(int x, int y) {
|
||||||
|
|
||||||
if(m_rc_skip.contains(pt)) {
|
if(m_rc_skip.contains(pt)) {
|
||||||
m_skip_selected = !m_skip_selected;
|
m_skip_selected = !m_skip_selected;
|
||||||
|
m_owner->set_skip(m_skip_selected);
|
||||||
m_owner->update(m_rc.left()+m_rc_skip.left(), m_rc.top()+m_rc_skip.top(), m_rc_skip.width(), m_rc_skip.height());
|
m_owner->update(m_rc.left()+m_rc_skip.left(), m_rc.top()+m_rc_skip.top(), m_rc_skip.width(), m_rc_skip.height());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
if(m_rc_progress.contains(pt)) {
|
||||||
|
m_progress_pressed = true;
|
||||||
|
// TODO: 暂停播放,按比例计算出点击位置占整个录像时长的百分比,定位到此位置准备播放。
|
||||||
|
// TODO: 如果点击的位置是进度条指示标志,则仅暂停播放
|
||||||
|
m_owner->pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bar::onMouseRelease(int x, int y, Qt::MouseButton button) {
|
||||||
|
// 我们只关心左键释放
|
||||||
|
if(button != Qt::LeftButton)
|
||||||
|
return;
|
||||||
|
if(m_progress_pressed) {
|
||||||
|
m_progress_pressed = false;
|
||||||
|
qDebug("resume at %dms.", m_resume_ms);
|
||||||
|
m_owner->resume(true, m_resume_ms);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Bar::get_speed() {
|
int Bar::get_speed() {
|
||||||
|
|
|
@ -84,7 +84,8 @@ public:
|
||||||
QRect rc(){return m_rc;}
|
QRect rc(){return m_rc;}
|
||||||
|
|
||||||
void onMouseMove(int x, int y);
|
void onMouseMove(int x, int y);
|
||||||
void onMousePress(int x, int y);
|
void onMousePress(int x, int y, Qt::MouseButton button);
|
||||||
|
void onMouseRelease(int x, int y, Qt::MouseButton button);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _init_imgages();
|
void _init_imgages();
|
||||||
|
@ -94,7 +95,7 @@ private:
|
||||||
MainWindow* m_owner;
|
MainWindow* m_owner;
|
||||||
|
|
||||||
uint32_t m_total_ms; // 录像的总时长
|
uint32_t m_total_ms; // 录像的总时长
|
||||||
uint32_t m_passed_ms; // 已经播放了的时长
|
uint32_t m_played_ms; // 已经播放了的时长
|
||||||
int m_percent; // 已经播放了的百分比(0~100)
|
int m_percent; // 已经播放了的百分比(0~100)
|
||||||
int m_percent_last_draw;
|
int m_percent_last_draw;
|
||||||
QString m_str_total_time;
|
QString m_str_total_time;
|
||||||
|
@ -139,6 +140,10 @@ private:
|
||||||
int m_speed_hover; // speed__max=no-hover
|
int m_speed_hover; // speed__max=no-hover
|
||||||
bool m_skip_selected;
|
bool m_skip_selected;
|
||||||
bool m_skip_hover;
|
bool m_skip_hover;
|
||||||
|
bool m_progress_hover;
|
||||||
|
bool m_progress_pressed;
|
||||||
|
|
||||||
|
uint32_t m_resume_ms; // after drag progress-pointer, resume play from here.
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BAR_H
|
#endif // BAR_H
|
||||||
|
|
|
@ -110,20 +110,7 @@ void MainWindow::_do_first_run() {
|
||||||
// connect(m_thr_data, SIGNAL(signal_download(DownloadParam*)), this, SLOT(_do_download(DownloadParam*)));
|
// connect(m_thr_data, SIGNAL(signal_download(DownloadParam*)), this, SLOT(_do_download(DownloadParam*)));
|
||||||
m_thr_data->start();
|
m_thr_data->start();
|
||||||
|
|
||||||
_start_play_thread();
|
//_start_play_thread();
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::_start_play_thread() {
|
|
||||||
if(m_thr_play) {
|
|
||||||
m_thr_play->stop();
|
|
||||||
//m_thr_play->wait();
|
|
||||||
|
|
||||||
disconnect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
|
||||||
|
|
||||||
delete m_thr_play;
|
|
||||||
m_thr_play = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_thr_play = new ThrPlay(this);
|
m_thr_play = new ThrPlay(this);
|
||||||
connect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
connect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
||||||
|
|
||||||
|
@ -131,6 +118,24 @@ void MainWindow::_start_play_thread() {
|
||||||
m_thr_play->start();
|
m_thr_play->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void MainWindow::_start_play_thread() {
|
||||||
|
// if(m_thr_play) {
|
||||||
|
// m_thr_play->stop();
|
||||||
|
// //m_thr_play->wait();
|
||||||
|
|
||||||
|
// disconnect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
||||||
|
|
||||||
|
// delete m_thr_play;
|
||||||
|
// m_thr_play = nullptr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// m_thr_play = new ThrPlay(this);
|
||||||
|
// connect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
||||||
|
|
||||||
|
// m_thr_play->speed(m_bar.get_speed());
|
||||||
|
// m_thr_play->start();
|
||||||
|
//}
|
||||||
|
|
||||||
void MainWindow::set_speed(int s) {
|
void MainWindow::set_speed(int s) {
|
||||||
if(m_thr_play)
|
if(m_thr_play)
|
||||||
m_thr_play->speed(s);
|
m_thr_play->speed(s);
|
||||||
|
@ -203,11 +208,17 @@ void MainWindow::pause() {
|
||||||
m_play_state = PLAY_STATE_PAUSE;
|
m_play_state = PLAY_STATE_PAUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::resume() {
|
void MainWindow::resume(bool relocate, uint32_t ms) {
|
||||||
if(m_play_state == PLAY_STATE_PAUSE)
|
if(m_play_state == PLAY_STATE_PAUSE) {
|
||||||
m_thr_play->resume();
|
if(relocate)
|
||||||
else if(m_play_state == PLAY_STATE_STOP)
|
m_thr_data->restart(ms);
|
||||||
_start_play_thread();
|
m_thr_play->resume(relocate, ms);
|
||||||
|
}
|
||||||
|
else if(m_play_state == PLAY_STATE_STOP) {
|
||||||
|
// _start_play_thread();
|
||||||
|
m_thr_data->restart(0);
|
||||||
|
m_thr_play->resume(true, 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_play_state = PLAY_STATE_RUNNING;
|
m_play_state = PLAY_STATE_RUNNING;
|
||||||
}
|
}
|
||||||
|
@ -432,12 +443,22 @@ void MainWindow::mouseMoveEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::mousePressEvent(QMouseEvent *e) {
|
void MainWindow::mousePressEvent(QMouseEvent *e) {
|
||||||
// QApplication::instance()->exit(0);
|
|
||||||
// return;
|
|
||||||
if(!m_show_default) {
|
if(!m_show_default) {
|
||||||
QRect rc = m_bar.rc();
|
QRect rc = m_bar.rc();
|
||||||
if(rc.contains(e->pos())) {
|
if(rc.contains(e->pos())) {
|
||||||
m_bar.onMousePress(e->x(), e->y());
|
m_bar.onMousePress(e->x(), e->y(), e->button());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
qDebug("mouse release.");
|
||||||
|
// if(!m_show_default) {
|
||||||
|
// QRect rc = m_bar.rc();
|
||||||
|
// if(rc.contains(e->pos())) {
|
||||||
|
// m_bar.onMouseRelease(e->x(), e->y(), e->button());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
m_bar.onMouseRelease(e->x(), e->y(), e->button());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
void set_resource(const QString& res);
|
void set_resource(const QString& res);
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
void resume();
|
void resume(bool relocate, uint32_t ms);
|
||||||
void restart();
|
void restart();
|
||||||
void set_speed(int s);
|
void set_speed(int s);
|
||||||
void set_skip(bool s);
|
void set_skip(bool s);
|
||||||
|
@ -44,8 +44,9 @@ private:
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
void mousePressEvent(QMouseEvent *e);
|
void mousePressEvent(QMouseEvent *e);
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e);
|
||||||
|
|
||||||
void _start_play_thread();
|
// void _start_play_thread();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void _do_first_run(); // 默认界面加载完成后,开始播放操作(可能会进行数据下载)
|
void _do_first_run(); // 默认界面加载完成后,开始播放操作(可能会进行数据下载)
|
||||||
|
|
|
@ -23,7 +23,12 @@ 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_need_restart = false;
|
||||||
|
m_wait_restart = false;
|
||||||
|
m_need_show_kf = false;
|
||||||
|
|
||||||
|
m_file_idx = 0;
|
||||||
|
m_offset = 0;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
m_data_path_base = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
m_data_path_base = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
|
@ -138,54 +143,12 @@ void ThrData::_run() {
|
||||||
|
|
||||||
|
|
||||||
UpdateData* dat = new UpdateData(m_hdr);
|
UpdateData* dat = new UpdateData(m_hdr);
|
||||||
// dat->alloc_data(sizeof(TS_RECORD_HEADER));
|
|
||||||
// memcpy(dat->data_buf(), &m_hdr, sizeof(TS_RECORD_HEADER));
|
|
||||||
emit signal_update_data(dat);
|
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;
|
QFile* fdata = nullptr;
|
||||||
uint32_t file_idx = 0;
|
//uint32_t file_idx = 0;
|
||||||
uint32_t start_offset = 0;
|
//uint32_t start_offset = 0;
|
||||||
qint64 file_size = 0;
|
qint64 file_size = 0;
|
||||||
qint64 file_processed = 0;
|
qint64 file_processed = 0;
|
||||||
qint64 read_len = 0;
|
qint64 read_len = 0;
|
||||||
|
@ -196,8 +159,20 @@ void ThrData::_run() {
|
||||||
if(m_need_stop)
|
if(m_need_stop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(m_need_restart) {
|
||||||
|
if(fdata) {
|
||||||
|
fdata->close();
|
||||||
|
delete fdata;
|
||||||
|
fdata = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_wait_restart = true;
|
||||||
|
msleep(50);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 如果所有文件都已经处理完了,则等待(可能用户会拖动滚动条,或者重新播放)
|
// 如果所有文件都已经处理完了,则等待(可能用户会拖动滚动条,或者重新播放)
|
||||||
if(file_idx >= m_hdr.info.dat_file_count) {
|
if(m_file_idx >= m_hdr.info.dat_file_count) {
|
||||||
msleep(500);
|
msleep(500);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -222,10 +197,12 @@ void ThrData::_run() {
|
||||||
for(int i = 0; i < pkg_need_add; ++i) {
|
for(int i = 0; i < pkg_need_add; ++i) {
|
||||||
if(m_need_stop)
|
if(m_need_stop)
|
||||||
return;
|
return;
|
||||||
|
if(m_need_restart)
|
||||||
|
break;
|
||||||
|
|
||||||
// 如果数据文件尚未打开,则打开它
|
// 如果数据文件尚未打开,则打开它
|
||||||
if(fdata == nullptr) {
|
if(fdata == nullptr) {
|
||||||
str_fidx.sprintf("%d", file_idx+1);
|
str_fidx.sprintf("%d", m_file_idx+1);
|
||||||
QString tpd_fname = QString("%1/tp-rdp-%2.tpd").arg(m_data_path, str_fidx);
|
QString tpd_fname = QString("%1/tp-rdp-%2.tpd").arg(m_data_path, str_fidx);
|
||||||
tpd_fname = QDir::toNativeSeparators(tpd_fname);
|
tpd_fname = QDir::toNativeSeparators(tpd_fname);
|
||||||
|
|
||||||
|
@ -236,13 +213,13 @@ void ThrData::_run() {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(m_need_stop)
|
if(m_need_stop)
|
||||||
return;
|
return;
|
||||||
if(!m_thr_download.is_running() || m_thr_download.is_tpd_downloaded(file_idx))
|
if(!m_thr_download.is_running() || m_thr_download.is_tpd_downloaded(m_file_idx))
|
||||||
break;
|
break;
|
||||||
msleep(100);
|
msleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下载失败了
|
// 下载失败了
|
||||||
if(!m_thr_download.is_tpd_downloaded(file_idx))
|
if(!m_thr_download.is_tpd_downloaded(m_file_idx))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,15 +233,22 @@ void ThrData::_run() {
|
||||||
|
|
||||||
file_size = fdata->size();
|
file_size = fdata->size();
|
||||||
file_processed = 0;
|
file_processed = 0;
|
||||||
qDebug("Open file, processed: %" PRId64 ", size: %" PRId64, file_processed, file_size);
|
qDebug("Open file tp-rdp-%d.tpd, processed: %" PRId64 ", size: %" PRId64, m_file_idx+1, file_processed, file_size);
|
||||||
}
|
}
|
||||||
// qDebug("B processed: %" PRId64 ", size: %" PRId64, file_processed, file_size);
|
// qDebug("B processed: %" PRId64 ", size: %" PRId64, file_processed, file_size);
|
||||||
|
|
||||||
|
// 如果指定了起始偏移,则跳过这部分数据
|
||||||
|
if(m_offset > 0) {
|
||||||
|
fdata->seek(m_offset);
|
||||||
|
file_processed = m_offset;
|
||||||
|
m_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------
|
//----------------------------------
|
||||||
// 读取一个数据包
|
// 读取一个数据包
|
||||||
//----------------------------------
|
//----------------------------------
|
||||||
if(file_size - file_processed < sizeof(TS_RECORD_PKG)) {
|
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));
|
qDebug("invaid tp-rdp-%d.tpd file, filesize=%" PRId64 ", processed=%" PRId64 ", need=%d.", m_file_idx+1, file_size, file_processed, sizeof(TS_RECORD_PKG));
|
||||||
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -274,14 +258,14 @@ void ThrData::_run() {
|
||||||
// if(read_len == 0)
|
// if(read_len == 0)
|
||||||
// break;
|
// break;
|
||||||
if(read_len != sizeof(TS_RECORD_PKG)) {
|
if(read_len != sizeof(TS_RECORD_PKG)) {
|
||||||
qDebug("invaid tp-rdp-%d.tpd file, read_len=%" PRId64 " (1).", file_idx+1, read_len);
|
qDebug("invaid tp-rdp-%d.tpd file, read_len=%" PRId64 " (1).", m_file_idx+1, read_len);
|
||||||
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
file_processed += sizeof(TS_RECORD_PKG);
|
file_processed += sizeof(TS_RECORD_PKG);
|
||||||
|
|
||||||
if(file_size - file_processed < pkg.size) {
|
if(file_size - file_processed < pkg.size) {
|
||||||
qDebug("invaid tp-rdp-%d.tpd file (2).", file_idx+1);
|
qDebug("invaid tp-rdp-%d.tpd file (2).", m_file_idx+1);
|
||||||
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -292,7 +276,7 @@ void ThrData::_run() {
|
||||||
|
|
||||||
QByteArray pkg_data = fdata->read(pkg.size);
|
QByteArray pkg_data = fdata->read(pkg.size);
|
||||||
if(pkg_data.size() != pkg.size) {
|
if(pkg_data.size() != pkg.size) {
|
||||||
qDebug("invaid tp-rdp-%d.tpd file, read_len=%" PRId64 " (3).", file_idx+1, read_len);
|
qDebug("invaid tp-rdp-%d.tpd file, read_len=%" PRId64 " (3).", m_file_idx+1, read_len);
|
||||||
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -300,30 +284,23 @@ void ThrData::_run() {
|
||||||
|
|
||||||
UpdateData* dat = new UpdateData();
|
UpdateData* dat = new UpdateData();
|
||||||
if(!dat->parse(pkg, pkg_data)) {
|
if(!dat->parse(pkg, pkg_data)) {
|
||||||
qDebug("invaid tp-rdp-%d.tpd file (4).", file_idx+1);
|
qDebug("invaid tp-rdp-%d.tpd file (4).", m_file_idx+1);
|
||||||
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 拖动滚动条后,需要显示一次关键帧数据,然后跳过后续关键帧。
|
||||||
// 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 = 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, 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) {
|
if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
|
||||||
qDebug("----key frame: %ld, processed=%" PRId64 ", pkg.size=%d", pkg.time_ms, file_processed, pkg.size);
|
qDebug("----key frame: %ld, processed=%" PRId64 ", pkg.size=%d", pkg.time_ms, file_processed, pkg.size);
|
||||||
delete dat;
|
if(m_need_show_kf) {
|
||||||
dat = nullptr;
|
m_need_show_kf = false;
|
||||||
|
qDebug("++ show keyframe.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qDebug("-- skip keyframe.");
|
||||||
|
delete dat;
|
||||||
|
dat = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -331,32 +308,75 @@ void ThrData::_run() {
|
||||||
if(dat) {
|
if(dat) {
|
||||||
m_locker.lock();
|
m_locker.lock();
|
||||||
m_data.enqueue(dat);
|
m_data.enqueue(dat);
|
||||||
// qDebug("queue data count: %d", m_data.size());
|
|
||||||
m_locker.unlock();
|
m_locker.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 让线程调度器让播放线程有机会执行
|
||||||
msleep(1);
|
msleep(1);
|
||||||
|
|
||||||
// 如果此文件已经处理完毕,则关闭文件,这样下次处理一个新的文件
|
// 如果此文件已经处理完毕,则关闭文件,这样下次处理一个新的文件
|
||||||
// qDebug("C processed: %" PRId64 ", size: %" PRId64, file_processed, file_size);
|
|
||||||
if(file_processed >= file_size) {
|
if(file_processed >= file_size) {
|
||||||
fdata->close();
|
fdata->close();
|
||||||
delete fdata;
|
delete fdata;
|
||||||
fdata = nullptr;
|
fdata = nullptr;
|
||||||
file_idx++;
|
m_file_idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(file_idx >= m_hdr.info.dat_file_count) {
|
if(m_file_idx >= m_hdr.info.dat_file_count) {
|
||||||
UpdateData* dat = new UpdateData(TYPE_END);
|
UpdateData* dat = new UpdateData(TYPE_END);
|
||||||
m_locker.lock();
|
m_locker.lock();
|
||||||
m_data.enqueue(dat);
|
m_data.enqueue(dat);
|
||||||
// qDebug("queue data count: %d", m_data.size());
|
|
||||||
m_locker.unlock();
|
m_locker.unlock();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ThrData::restart(uint32_t start_ms) {
|
||||||
|
// 让处理线程处理完当前循环,然后等待
|
||||||
|
m_need_restart = true;
|
||||||
|
|
||||||
|
// 确保处理线程已经处理完当前循环
|
||||||
|
for(;;) {
|
||||||
|
msleep(50);
|
||||||
|
if(m_need_stop)
|
||||||
|
return;
|
||||||
|
if(m_wait_restart)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空待播放队列
|
||||||
|
_clear_data();
|
||||||
|
|
||||||
|
if(start_ms == 0) {
|
||||||
|
m_offset = 0;
|
||||||
|
m_file_idx = 0;
|
||||||
|
m_need_show_kf = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 找到最接近 start_ms 但小于它的关键帧
|
||||||
|
size_t i = 0;
|
||||||
|
for(i = 0; i < m_kf.size(); ++i) {
|
||||||
|
if(m_kf[i].time_ms > start_ms)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(i > 0)
|
||||||
|
i--;
|
||||||
|
|
||||||
|
// 指定要播放的数据的开始位置
|
||||||
|
m_offset = m_kf[i].offset;
|
||||||
|
m_file_idx = m_kf[i].file_index;
|
||||||
|
m_need_show_kf = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug("RESTART: offset=%d, file_idx=%d", m_offset, m_file_idx);
|
||||||
|
|
||||||
|
// 让处理线程继续
|
||||||
|
m_wait_restart = false;
|
||||||
|
m_need_restart = false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ThrData::_load_header() {
|
bool ThrData::_load_header() {
|
||||||
QString msg;
|
QString msg;
|
||||||
qDebug() << "PATH_BASE: " << m_data_path;
|
qDebug() << "PATH_BASE: " << m_data_path;
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
virtual void run();
|
virtual void run();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
void restart(uint32_t start_ms); // 重新从指定时间开始播放
|
||||||
|
|
||||||
bool have_more_data();
|
bool have_more_data();
|
||||||
|
|
||||||
|
@ -94,6 +95,12 @@ private:
|
||||||
|
|
||||||
TS_RECORD_HEADER m_hdr;
|
TS_RECORD_HEADER m_hdr;
|
||||||
KeyFrames m_kf;
|
KeyFrames m_kf;
|
||||||
|
|
||||||
|
bool m_need_restart;
|
||||||
|
bool m_wait_restart;
|
||||||
|
bool m_need_show_kf;
|
||||||
|
uint32_t m_file_idx;
|
||||||
|
uint32_t m_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // THR_DATA_H
|
#endif // THR_DATA_H
|
||||||
|
|
|
@ -25,8 +25,7 @@ ThrPlay::ThrPlay(MainWindow* mainwnd) {
|
||||||
m_need_pause = false;
|
m_need_pause = false;
|
||||||
m_speed = 1;
|
m_speed = 1;
|
||||||
m_skip = false;
|
m_skip = false;
|
||||||
// m_res = res;
|
m_start_ms = 0;
|
||||||
// m_thr_data = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrPlay::~ThrPlay() {
|
ThrPlay::~ThrPlay() {
|
||||||
|
@ -64,10 +63,18 @@ void ThrPlay::_notify_error(const QString& msg) {
|
||||||
emit signal_update_data(_msg);
|
emit signal_update_data(_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ThrPlay::resume(bool relocate, uint32_t start_ms) {
|
||||||
|
if(relocate) {
|
||||||
|
m_start_ms = start_ms;
|
||||||
|
m_first_run = true;
|
||||||
|
}
|
||||||
|
m_need_pause = false;
|
||||||
|
}
|
||||||
|
|
||||||
void ThrPlay::run() {
|
void ThrPlay::run() {
|
||||||
|
|
||||||
ThrData* thr_data = m_mainwnd->get_thr_data();
|
ThrData* thr_data = m_mainwnd->get_thr_data();
|
||||||
bool first_run = true;
|
m_first_run = true;
|
||||||
uint32_t last_time_ms = 0;
|
uint32_t last_time_ms = 0;
|
||||||
uint32_t last_pass_ms = 0;
|
uint32_t last_pass_ms = 0;
|
||||||
|
|
||||||
|
@ -83,11 +90,20 @@ void ThrPlay::run() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(first_run) {
|
if(m_first_run) {
|
||||||
first_run = false;
|
m_first_run = false;
|
||||||
_notify_message("");
|
_notify_message("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// 2. 根据数据包的信息,等待到播放时间点
|
// 2. 根据数据包的信息,等待到播放时间点
|
||||||
uint32_t need_wait_ms = 0;
|
uint32_t need_wait_ms = 0;
|
||||||
uint32_t this_time_ms = dat->get_time();
|
uint32_t this_time_ms = dat->get_time();
|
||||||
|
@ -119,6 +135,14 @@ void ThrPlay::run() {
|
||||||
if(m_need_stop)
|
if(m_need_stop)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if(m_start_ms > 0) {
|
||||||
|
// if(dat) {
|
||||||
|
// delete dat;
|
||||||
|
// dat = nullptr;
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
time_wait *= m_speed;
|
time_wait *= m_speed;
|
||||||
|
|
||||||
// 如果已经在等待长时间无操作区间内,用户设置了跳过无操作区间,则将超过0.5秒的等待时间压缩至0.5秒。
|
// 如果已经在等待长时间无操作区间内,用户设置了跳过无操作区间,则将超过0.5秒的等待时间压缩至0.5秒。
|
||||||
|
@ -143,6 +167,14 @@ void ThrPlay::run() {
|
||||||
|
|
||||||
if(m_need_stop)
|
if(m_need_stop)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// if(m_start_ms > 0) {
|
||||||
|
// if(dat) {
|
||||||
|
// delete dat;
|
||||||
|
// dat = nullptr;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
last_time_ms = this_time_ms;
|
last_time_ms = this_time_ms;
|
||||||
|
|
|
@ -19,7 +19,7 @@ public:
|
||||||
virtual void run();
|
virtual void run();
|
||||||
void stop();
|
void stop();
|
||||||
void pause() {m_need_pause = true;}
|
void pause() {m_need_pause = true;}
|
||||||
void resume() {m_need_pause = false;}
|
void resume(bool relocate, uint32_t start_ms);
|
||||||
void speed(int s) {if(s >= 1 && s <= 16) m_speed = s;}
|
void speed(int s) {if(s >= 1 && s <= 16) m_speed = s;}
|
||||||
void skip(bool s) {m_skip = s;}
|
void skip(bool s) {m_skip = s;}
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ private:
|
||||||
bool m_need_pause;
|
bool m_need_pause;
|
||||||
int m_speed;
|
int m_speed;
|
||||||
bool m_skip;
|
bool m_skip;
|
||||||
|
bool m_first_run;
|
||||||
|
uint32_t m_start_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // THR_PLAY_H
|
#endif // THR_PLAY_H
|
||||||
|
|
Loading…
Reference in New Issue