viewer: improved frame queue and linked window

Improves minor issues with frame queue implemented in earlier commit. Also links
ViewerWindow with the queue and a separate timer to make it much smoother.
This commit is contained in:
itsmattkc
2020-05-09 16:02:18 +10:00
parent 8c4c6ba2a5
commit 00248de49c
13 changed files with 370 additions and 130 deletions
+106 -70
View File
@@ -63,15 +63,13 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
sizer_ = new ViewerSizer();
stack_->addWidget(sizer_);
ViewerDisplayWidget* main_widget = new ViewerDisplayWidget();
connect(main_widget, &ViewerDisplayWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
connect(main_widget, &ViewerDisplayWidget::CursorColor, this, &ViewerWidget::CursorColor);
connect(main_widget, &ViewerDisplayWidget::LoadedBuffer, this, &ViewerWidget::LoadedBuffer);
connect(main_widget, &ViewerDisplayWidget::ColorProcessorChanged, this, &ViewerWidget::ColorProcessorChanged);
connect(main_widget, &ViewerDisplayWidget::ColorManagerChanged, this, &ViewerWidget::ColorManagerChanged);
connect(sizer_, &ViewerSizer::RequestMatrix, main_widget, &ViewerDisplayWidget::SetMatrix);
sizer_->SetWidget(main_widget);
gl_widgets_.append(main_widget);
display_widget_ = new ViewerDisplayWidget();
connect(display_widget_, &ViewerDisplayWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
connect(display_widget_, &ViewerDisplayWidget::CursorColor, this, &ViewerWidget::CursorColor);
connect(display_widget_, &ViewerDisplayWidget::ColorProcessorChanged, this, &ViewerWidget::ColorProcessorChanged);
connect(display_widget_, &ViewerDisplayWidget::ColorManagerChanged, this, &ViewerWidget::ColorManagerChanged);
connect(sizer_, &ViewerSizer::RequestMatrix, display_widget_, &ViewerDisplayWidget::SetMatrix);
sizer_->SetWidget(display_widget_);
// Create waveform view when audio is connected and video isn't
waveform_view_ = new AudioWaveformView();
@@ -117,6 +115,15 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
SetAutoMaxScrollBar(true);
}
ViewerWidget::~ViewerWidget()
{
QList<ViewerWindow*> windows = windows_;
foreach (ViewerWindow* window, windows) {
delete window;
}
}
void ViewerWidget::TimeChangedEvent(const int64_t &i)
{
if (!time_changed_from_timer_) {
@@ -133,7 +140,7 @@ void ViewerWidget::TimeChangedEvent(const int64_t &i)
PushScrubbedAudio();
main_gl_widget()->SetTime(time_set);
display_widget_->SetTime(time_set);
}
last_time_ = i;
@@ -170,8 +177,9 @@ void ViewerWidget::ConnectNodeInternal(ViewerOutput *n)
using_manager = nullptr;
}
foreach (ViewerDisplayWidget* glw, gl_widgets_) {
glw->ConnectColorManager(using_manager);
display_widget_->ConnectColorManager(using_manager);
foreach (ViewerWindow* window, windows_) {
window->display_widget()->ConnectColorManager(using_manager);
}
divider_ = CalculateDivider();
@@ -202,8 +210,9 @@ void ViewerWidget::DisconnectNodeInternal(ViewerOutput *n)
// Effectively disables the viewer and clears the state
SizeChangedSlot(0, 0);
foreach (ViewerDisplayWidget* glw, gl_widgets_) {
glw->DisconnectColorManager();
display_widget_->DisconnectColorManager();
foreach (ViewerWindow* window, windows_) {
window->display_widget()->DisconnectColorManager();
}
waveform_view_->ConnectTimelinePoints(nullptr);
@@ -236,14 +245,9 @@ void ViewerWidget::resizeEvent(QResizeEvent *event)
UpdateMinimumScale();
}
const QList<ViewerDisplayWidget*> &ViewerWidget::gl_widgets() const
ViewerDisplayWidget *ViewerWidget::display_widget() const
{
return gl_widgets_;
}
ViewerDisplayWidget *ViewerWidget::main_gl_widget() const
{
return gl_widgets_.first();
return display_widget_;
}
void ViewerWidget::TogglePlayPause()
@@ -282,8 +286,9 @@ void ViewerWidget::SetOverrideSize(int width, int height)
void ViewerWidget::SetMatrix(const QMatrix4x4 &mat)
{
foreach (ViewerDisplayWidget* glw, gl_widgets_) {
glw->SetMatrix(mat);
display_widget_->SetMatrix(mat);
foreach (ViewerWindow* vw, windows_) {
vw->display_widget()->SetMatrix(mat);
}
}
@@ -306,19 +311,19 @@ void ViewerWidget::SetFullScreen(QScreen *screen)
ViewerWindow* vw = new ViewerWindow(this);
vw->showFullScreen();
vw->setGeometry(screen->geometry());
vw->gl_widget()->ConnectColorManager(main_gl_widget()->color_manager());
main_gl_widget()->ConnectSibling(vw->gl_widget());
vw->showFullScreen();
vw->display_widget()->ConnectColorManager(color_manager());
connect(vw, &ViewerWindow::destroyed, this, &ViewerWidget::WindowAboutToClose);
connect(vw->gl_widget(), &ViewerDisplayWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
connect(vw->display_widget(), &ViewerDisplayWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
if (GetConnectedNode()) {
vw->SetResolution(GetConnectedNode()->video_params().width(), GetConnectedNode()->video_params().height());
}
vw->display_widget()->SetImage(display_widget_->last_loaded_buffer());
windows_.append(vw);
gl_widgets_.append(vw->gl_widget());
}
void ViewerWidget::ForceUpdate()
@@ -334,27 +339,29 @@ VideoRenderBackend *ViewerWidget::video_renderer() const
ColorManager *ViewerWidget::color_manager() const
{
return main_gl_widget()->color_manager();
return display_widget_->color_manager();
}
void ViewerWidget::SetGizmos(Node *node)
{
main_gl_widget()->SetTimeTarget(GetConnectedNode());
main_gl_widget()->SetGizmos(node);
display_widget_->SetTimeTarget(GetConnectedNode());
display_widget_->SetGizmos(node);
}
void ViewerWidget::UpdateTextureFromNode(const rational& time)
{
{
QMutexLocker locker(&playback_frame_queue_lock_);
while (!playback_frame_queue_.isEmpty()) {
PlaybackFrame pf = playback_frame_queue_.takeFirst();
QMutexLocker locker(playback_queue_.lock());
while (!playback_queue_.isEmpty()) {
const ViewerPlaybackFrame& pf = playback_queue_.first();
if (pf.timestamp == time) {
// Frame was in queue, no need to decode anything
main_gl_widget()->SetImageFromLoadBuffer(pf.frame.get());
SetDisplayImage(pf.frame, true);
QtConcurrent::run(this, &ViewerWidget::FillPlaybackQueue);
return;
} else {
playback_queue_.removeFirst();
}
}
}
@@ -365,10 +372,10 @@ void ViewerWidget::UpdateTextureFromNode(const rational& time)
if (!frame_fn.isEmpty()) {
FramePtr f = DecodeCachedImage(frame_fn);
main_gl_widget()->SetImageFromLoadBuffer(f.get());
SetDisplayImage(f, false);
}
} else {
main_gl_widget()->SetImageFromLoadBuffer(nullptr);
SetDisplayImage(nullptr, false);
video_renderer_->UpdateLastRequestedTime(time);
}
}
@@ -393,9 +400,12 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
playback_speed_);
}
start_msec_ = QDateTime::currentMSecsSinceEpoch();
start_timestamp_ = ruler()->GetTime();
playback_frame_queue_next_frame_ = start_timestamp_;
playback_queue_next_frame_ = ruler()->GetTime();
playback_timer_.Start(playback_queue_next_frame_, playback_speed_, timebase_dbl());
foreach (ViewerWindow* window, windows_) {
window->Play(playback_queue_next_frame_, playback_speed_, timebase());
}
controls_->ShowPauseButton();
@@ -404,10 +414,10 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
if (playback_is_audio_only_) {
connect(AudioManager::instance(), &AudioManager::OutputNotified, this, &ViewerWidget::PlaybackTimerUpdate);
} else {
FillPlaybackQueue();
connect(main_gl_widget(), &ViewerDisplayWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate);
connect(display_widget_, &ViewerDisplayWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate);
}
FillPlaybackQueue();
}
void ViewerWidget::PushScrubbedAudio()
@@ -436,7 +446,7 @@ int ViewerWidget::CalculateDivider()
{
if (GetConnectedNode() && Config::Current()["AutoSelectDivider"].toBool()) {
int long_side_of_video = qMax(GetConnectedNode()->video_params().width(), GetConnectedNode()->video_params().height());
int long_side_of_widget = qMax(main_gl_widget()->width(), main_gl_widget()->height());
int long_side_of_widget = qMax(display_widget_->width(), display_widget_->height());
return qMax(1, long_side_of_video / long_side_of_widget);
}
@@ -465,12 +475,16 @@ void ViewerWidget::SetColorTransform(const ColorTransform &transform, ViewerDisp
void ViewerWidget::FillPlaybackQueue()
{
playback_frame_queue_lock_.lock();
while (playback_frame_queue_.size() < 8) {
playback_queue_.lock()->lock();
foreach (ViewerWindow* window, windows_) {
window->queue()->lock()->lock();
}
while (playback_queue_.size() < 8) {
// Load frame from cache
FramePtr frame = nullptr;
rational rtime = Timecode::timestamp_to_time(playback_frame_queue_next_frame_,
rational rtime = Timecode::timestamp_to_time(playback_queue_next_frame_,
timebase());
QString frame_fn = GetCachedFilenameFromTime(rtime);
@@ -479,15 +493,25 @@ void ViewerWidget::FillPlaybackQueue()
frame = DecodeCachedImage(frame_fn);
}
playback_frame_queue_.append({rtime, frame});
ViewerPlaybackFrame f = {rtime, frame};
playback_queue_.append(f);
foreach (ViewerWindow* window, windows_) {
window->queue()->append(f);
}
if (!playback_speed_) {
break;
}
playback_frame_queue_next_frame_ += playback_speed_;
playback_queue_next_frame_ += playback_speed_;
}
playback_frame_queue_lock_.unlock();
foreach (ViewerWindow* window, windows_) {
window->queue()->lock()->unlock();
}
playback_queue_.lock()->unlock();
}
QString ViewerWidget::GetCachedFilenameFromTime(const rational &time)
@@ -543,6 +567,19 @@ FramePtr ViewerWidget::DecodeCachedImage(const QString &fn)
return frame;
}
void ViewerWidget::SetDisplayImage(FramePtr frame, bool main_only)
{
display_widget_->SetImage(frame);
if (!main_only) {
foreach (ViewerWindow* vw, windows_) {
vw->display_widget()->SetImage(frame);
}
}
emit LoadedBuffer(frame.get());
}
void ViewerWidget::UpdateStack()
{
if (GetConnectedNode()
@@ -616,10 +653,7 @@ void ViewerWidget::ContextMenuSetCustomSafeMargins()
void ViewerWidget::WindowAboutToClose()
{
ViewerWindow* vw = static_cast<ViewerWindow*>(sender());
windows_.removeAll(vw);
gl_widgets_.removeAll(vw->gl_widget());
windows_.removeOne(static_cast<ViewerWindow*>(sender()));
}
void ViewerWidget::ContextMenuScopeTriggered(QAction *action)
@@ -629,9 +663,7 @@ void ViewerWidget::ContextMenuScopeTriggered(QAction *action)
void ViewerWidget::RendererGeneratedFrame(FramePtr f)
{
foreach (ViewerDisplayWidget* glw, gl_widgets_) {
glw->SetImageFromLoadBuffer(f.get());
}
SetDisplayImage(f, false);
}
void ViewerWidget::UpdateRendererParameters()
@@ -652,7 +684,7 @@ void ViewerWidget::UpdateRendererParameters()
video_renderer_->InvalidateCache(TimeRange(0, GetConnectedNode()->Length()), nullptr);
}
main_gl_widget()->SetVideoParams(vparam);
display_widget_->SetVideoParams(vparam);
AudioRenderingParams aparam(GetConnectedNode()->audio_params(),
SampleFormat::kInternalFormat);
@@ -809,12 +841,18 @@ void ViewerWidget::Pause()
if (playback_is_audio_only_) {
disconnect(AudioManager::instance(), &AudioManager::OutputNotified, this, &ViewerWidget::PlaybackTimerUpdate);
} else {
disconnect(main_gl_widget(), &ViewerDisplayWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate);
disconnect(display_widget_, &ViewerDisplayWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate);
}
playback_frame_queue_lock_.lock();
playback_frame_queue_.clear();
playback_frame_queue_lock_.unlock();
foreach (ViewerWindow* window, windows_) {
window->Pause();
}
{
playback_queue_.lock()->lock();
playback_queue_.clear();
playback_queue_.lock()->unlock();
}
}
}
@@ -859,13 +897,15 @@ void ViewerWidget::ShuttleRight()
void ViewerWidget::SetColorTransform(const ColorTransform &transform)
{
SetColorTransform(transform, main_gl_widget());
SetColorTransform(transform, display_widget_);
}
void ViewerWidget::SetSignalCursorColorEnabled(bool e)
{
foreach (ViewerDisplayWidget* glw, gl_widgets_) {
glw->SetSignalCursorColorEnabled(e);
display_widget_->SetSignalCursorColorEnabled(e);
foreach (ViewerWindow* vw, windows_) {
vw->display_widget()->SetSignalCursorColorEnabled(e);
}
}
@@ -881,11 +921,7 @@ void ViewerWidget::TimebaseChangedEvent(const rational &timebase)
void ViewerWidget::PlaybackTimerUpdate()
{
int64_t real_time = QDateTime::currentMSecsSinceEpoch() - start_msec_;
int64_t frames_since_start = qRound(static_cast<double>(real_time) / (timebase_dbl() * 1000));
int64_t current_time = start_timestamp_ + frames_since_start * playback_speed_;
int64_t current_time = playback_timer_.GetTimestampNow();
int64_t min_time, max_time;