From 2afa7ecafe2a7d7fb54db76ffdc45819e55353c4 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 2 Jan 2022 16:56:11 -0800 Subject: [PATCH] reworked viewer timers --- app/panel/viewer/viewerbase.cpp | 7 - app/panel/viewer/viewerbase.h | 2 - app/widget/viewer/viewer.cpp | 206 +++++++++------------------- app/widget/viewer/viewer.h | 10 +- app/widget/viewer/viewerdisplay.cpp | 81 ++++++++++- app/widget/viewer/viewerdisplay.h | 27 ++++ app/widget/viewer/viewerqueue.h | 10 ++ app/widget/viewer/viewerwindow.cpp | 39 ------ app/widget/viewer/viewerwindow.h | 23 +--- 9 files changed, 183 insertions(+), 222 deletions(-) diff --git a/app/panel/viewer/viewerbase.cpp b/app/panel/viewer/viewerbase.cpp index c9fc662a5..f06cd37b1 100644 --- a/app/panel/viewer/viewerbase.cpp +++ b/app/panel/viewer/viewerbase.cpp @@ -101,11 +101,4 @@ void ViewerPanelBase::SetViewerWidget(ViewerWidget *vw) SetTimeBasedWidget(vw); } -void ViewerPanelBase::closeEvent(QCloseEvent *e) -{ - static_cast(GetTimeBasedWidget())->Pause(); - - TimeBasedPanel::closeEvent(e); -} - } diff --git a/app/panel/viewer/viewerbase.h b/app/panel/viewer/viewerbase.h index f14b4519d..8135f7056 100644 --- a/app/panel/viewer/viewerbase.h +++ b/app/panel/viewer/viewerbase.h @@ -88,8 +88,6 @@ signals: protected: void SetViewerWidget(ViewerWidget *vw); - virtual void closeEvent(QCloseEvent* e) override; - }; } diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index 58e0e5fa7..e4be02aee 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -81,13 +81,13 @@ ViewerWidget::ViewerWidget(QWidget *parent) : display_widget_ = new ViewerDisplayWidget(); display_widget_->setAcceptDrops(true); display_widget_->SetShowWidgetBackground(true); + playback_devices_.append(display_widget_); 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(display_widget_, &ViewerDisplayWidget::DragEntered, this, &ViewerWidget::DragEntered); connect(display_widget_, &ViewerDisplayWidget::Dropped, this, &ViewerWidget::Dropped); - connect(display_widget_, &ViewerDisplayWidget::VisibilityChanged, this, &ViewerWidget::Pause); connect(display_widget_, &ViewerDisplayWidget::TextureChanged, this, &ViewerWidget::TextureChanged); connect(sizer_, &ViewerSizer::RequestScale, display_widget_, &ViewerDisplayWidget::SetMatrixZoom); connect(sizer_, &ViewerSizer::RequestTranslate, display_widget_, &ViewerDisplayWidget::SetMatrixTranslate); @@ -207,9 +207,8 @@ void ViewerWidget::ConnectNodeEvent(ViewerOutput *n) ColorManager* color_manager = n->project()->color_manager(); - display_widget_->ConnectColorManager(color_manager); - foreach (ViewerWindow* window, windows_) { - window->display_widget()->ConnectColorManager(color_manager); + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->ConnectColorManager(color_manager); } UpdateStack(); @@ -247,9 +246,8 @@ void ViewerWidget::DisconnectNodeEvent(ViewerOutput *n) // Effectively disables the viewer and clears the state SetViewerResolution(0, 0); - display_widget_->DisconnectColorManager(); - foreach (ViewerWindow* window, windows_) { - window->display_widget()->DisconnectColorManager(); + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->DisconnectColorManager(); } waveform_view_->SetViewer(nullptr); @@ -299,9 +297,8 @@ void ViewerWidget::SetColorMenuEnabled(bool enabled) void ViewerWidget::SetMatrix(const QMatrix4x4 &mat) { - display_widget_->SetMatrixCrop(mat); - foreach (ViewerWindow* vw, windows_) { - vw->display_widget()->SetMatrixCrop(mat); + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->SetMatrixCrop(mat); } } @@ -343,9 +340,11 @@ void ViewerWidget::SetFullScreen(QScreen *screen) vw->display_widget()->SetImage(QVariant::fromValue(display_widget()->GetCurrentTexture())); - (*vw->queue()) = playback_queue_; + playback_devices_.append(vw->display_widget()); + + (*vw->display_widget()->queue()) = *playback_devices_.first()->queue(); if (IsPlaying()) { - vw->Play(GetTimestamp(), playback_speed_, timebase()); + vw->display_widget()->Play(GetTimestamp(), playback_speed_, timebase()); } windows_.insert(screen, vw); @@ -402,10 +401,8 @@ bool ViewerWidget::ShouldForceWaveform() const void ViewerWidget::SetEmptyImage() { - display_widget()->SetBlank(); - - foreach (ViewerWindow *vw, windows_) { - vw->display_widget()->SetBlank(); + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->SetBlank(); } } @@ -539,85 +536,30 @@ void ViewerWidget::UpdateTextureFromNode() return; } + if (IsPlaying()) { + qDebug() << "UpdateTextureFromNode called while playing"; + return; + } + rational time = GetTime(); bool frame_exists_at_time = FrameExistsAtTime(time); bool frame_might_be_still = ViewerMightBeAStill(); - // Check playback queue for a frame - if (IsPlaying()) { - // We still run the playback queue even when FrameExistsAtTime returns false because we might be - // playing backwards and about to start showing frames, so the queue should be prepared for - // that. - bool popped = false; - - if (playback_queue_.empty()) { - - ForceRequeueFromCurrentTime(); - - } else { - while (!playback_queue_.empty()) { - - ViewerPlaybackFrame pf = playback_queue_.front(); - - if (pf.timestamp == time) { - - // Frame was in queue, no need to decode anything - SetDisplayImage(pf.frame, true); - return; - - } else if (pf.timestamp > time) { - - // The next frame in the queue is too new, so just do a regular update. Either the - // frame we want will arrive in time, or we'll just have to skip it. - break; - - } else { - - // Frame was too old, skip this frame - PopOldestFrameFromPlaybackQueue(); - if (popped) { - // We've already popped a frame in this loop, meaning a frame has been skipped - display_widget_->IncrementSkippedFrames(); - } else { - // Shown a frame and progressed to the next one - display_widget_->IncrementFrameCount(); - popped = true; - } - - if (playback_queue_.empty()) { - - ForceRequeueFromCurrentTime(); - break; - - } - - } - } - } - - } - if (frame_exists_at_time || frame_might_be_still) { // Frame was not in queue, will require rendering or decoding from cache - if (IsPlaying()) { - // Is playing, yet the queue above failed to retrieve the frame. We effectively do a quick - // reboot of the queue here, assuming the above loop has emptied it so far. - display_widget_->update(); - } else { - // Not playing, run a task to get the frame either from the cache or the renderer - RenderTicketWatcher* watcher = new RenderTicketWatcher(); - watcher->setProperty("start", QDateTime::currentMSecsSinceEpoch()); - watcher->setProperty("time", QVariant::fromValue(time)); - connect(watcher, &RenderTicketWatcher::Finished, this, &ViewerWidget::RendererGeneratedFrame); - nonqueue_watchers_.append(watcher); + // Not playing, run a task to get the frame either from the cache or the renderer + RenderTicketWatcher* watcher = new RenderTicketWatcher(); + watcher->setProperty("start", QDateTime::currentMSecsSinceEpoch()); + watcher->setProperty("time", QVariant::fromValue(time)); + connect(watcher, &RenderTicketWatcher::Finished, this, &ViewerWidget::RendererGeneratedFrame); + nonqueue_watchers_.append(watcher); - // Clear queue because we want this frame more than any others - if (!GetConnectedNode()->GetVideoAutoCacheEnabled() && !auto_cacher_.IsRenderingCustomRange()) { - ClearVideoAutoCacherQueue(); - } - - watcher->SetTicket(GetFrame(time, true)); + // Clear queue because we want this frame more than any others + if (!GetConnectedNode()->GetVideoAutoCacheEnabled() && !auto_cacher_.IsRenderingCustomRange()) { + ClearVideoAutoCacherQueue(); } + + watcher->SetTicket(GetFrame(time, true)); } else { // There is definitely no frame here, we can immediately flip to showing nothing nonqueue_watchers_.clear(); @@ -673,6 +615,7 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only) if (prequeue_length_ > 0) { prequeuing_video_ = true; + prequeue_count_ = 0; // We "prioritize" the frames, which means they're pushed to the top of the render queue, // we queue in reverse so that they're still queued in order @@ -715,16 +658,13 @@ void ViewerWidget::PauseInternal() playback_speed_ = 0; controls_->ShowPlayButton(); - disconnect(display_widget_, &ViewerDisplayWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate); - - foreach (ViewerWindow* window, windows_) { - window->Pause(); + foreach (ViewerDisplayWidget *dw, playback_devices_){ + dw->Pause(); } qDeleteAll(queue_watchers_); queue_watchers_.clear(); - playback_queue_.clear(); playback_backup_timer_.stop(); // Handle audio @@ -811,14 +751,10 @@ bool ViewerWidget::ViewerMightBeAStill() return GetConnectedNode() && GetConnectedNode()->GetConnectedTextureOutput() && GetConnectedNode()->GetVideoLength().isNull(); } -void ViewerWidget::SetDisplayImage(QVariant frame, bool main_only) +void ViewerWidget::SetDisplayImage(QVariant frame) { - display_widget_->SetImage(frame); - - if (!main_only) { - foreach (ViewerWindow* vw, windows_) { - vw->display_widget()->SetImage(frame); - } + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->SetImage(frame); } } @@ -876,19 +812,15 @@ void ViewerWidget::FinishPlayPreprocess() GetTime(), playback_speed_); } - playback_timer_.Start(playback_start_time, playback_speed_, timebase_dbl()); display_widget_->ResetFPSTimer(); - foreach (ViewerWindow* window, windows_) { - window->Play(playback_start_time, playback_speed_, timebase()); + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->Play(playback_start_time, playback_speed_, timebase()); } - if (display_widget_->isVisible()) { - connect(display_widget_, &ViewerDisplayWidget::frameSwapped, this, &ViewerWidget::PlaybackTimerUpdate); - } else { - playback_backup_timer_.setInterval(qFloor(timebase_dbl())); - playback_backup_timer_.start(); - } + // This is our timer for loading the queue and setting the time + playback_backup_timer_.setInterval(qFloor(timebase_dbl())); + playback_backup_timer_.start(); PlaybackTimerUpdate(); } @@ -909,15 +841,6 @@ int ViewerWidget::DeterminePlaybackQueueSize() return qMin(kMaxPreQueueSize, remaining_frames); } -void ViewerWidget::PopOldestFrameFromPlaybackQueue() -{ - playback_queue_.pop_front(); - - if (int(playback_queue_.size()) < DeterminePlaybackQueueSize()) { - RequestNextFrameForQueue(); - } -} - void ViewerWidget::UpdateStack() { rational new_tb; @@ -970,7 +893,9 @@ void ViewerWidget::ContextMenuSetCustomSafeMargins() void ViewerWidget::WindowAboutToClose() { - windows_.remove(windows_.key(static_cast(sender()))); + ViewerWindow *vw = static_cast(sender()); + windows_.remove(windows_.key(vw)); + playback_devices_.removeOne(vw->display_widget()); } void ViewerWidget::RendererGeneratedFrame() @@ -1017,13 +942,12 @@ void ViewerWidget::RendererGeneratedFrameForQueue() if (IsPlaying() || prequeuing_video_) { rational ts = watcher->property("time").value(); - playback_queue_.AppendTimewise({ts, frame}, playback_speed_); - - foreach (ViewerWindow* window, windows_) { - window->queue()->AppendTimewise({ts, frame}, playback_speed_); + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->queue()->AppendTimewise({ts, frame}, playback_speed_); } + prequeue_count_++; - if (prequeuing_video_ && int(playback_queue_.size()) == prequeue_length_) { + if (prequeuing_video_ && prequeue_count_ == prequeue_length_) { prequeuing_video_ = false; FinishPlayPreprocess(); } @@ -1251,10 +1175,8 @@ void ViewerWidget::SetColorTransform(const ColorTransform &transform) void ViewerWidget::SetSignalCursorColorEnabled(bool e) { - display_widget_->SetSignalCursorColorEnabled(e); - - foreach (ViewerWindow* vw, windows_) { - vw->display_widget()->SetSignalCursorColorEnabled(e); + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->SetSignalCursorColorEnabled(e); } } @@ -1270,7 +1192,7 @@ void ViewerWidget::TimebaseChangedEvent(const rational &timebase) void ViewerWidget::PlaybackTimerUpdate() { - rational current_time = Timecode::timestamp_to_time(playback_timer_.GetTimestampNow(), timebase()); + rational current_time = Timecode::timestamp_to_time(display_widget_->timer()->GetTimestampNow(), timebase()); rational min_time, max_time; @@ -1352,14 +1274,15 @@ void ViewerWidget::PlaybackTimerUpdate() } } - if (display_widget_->isVisible()) { - // Updating display widget - UpdateTextureFromNode(); - } else if (!windows_.empty()) { - // We still run the queue if windows are visible even if our own display widget isn't visible - while (!playback_queue_.empty() && playback_queue_.front().timestamp != GetTime()) { - PopOldestFrameFromPlaybackQueue(); - } + // We still run the queue if windows are visible even if our own display widget isn't visible + /*while (!playback_queue_.empty() && playback_queue_.front().timestamp != GetTime()) { + PopOldestFrameFromPlaybackQueue(); + }*/ + // NOTE: There should be some calculation here to determine how many frames need to be queued + RequestNextFrameForQueue(); + + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->queue()->PurgeBefore(current_time, playback_speed_); } } @@ -1398,10 +1321,10 @@ void ViewerWidget::LengthChangedSlot(const rational &length) void ViewerWidget::InterlacingChangedSlot(VideoParams::Interlacing interlacing) { // Automatically set a "sane" deinterlacing option - display_widget_->SetDeinterlacing(interlacing != VideoParams::kInterlaceNone); + bool deint = interlacing != VideoParams::kInterlaceNone; - foreach (ViewerWindow* vw, windows_) { - vw->display_widget()->SetDeinterlacing(interlacing != VideoParams::kInterlaceNone); + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->SetDeinterlacing(deint); } } @@ -1409,9 +1332,8 @@ void ViewerWidget::UpdateRendererVideoParameters() { VideoParams vp = GetConnectedNode()->GetVideoParams(); - display_widget_->SetVideoParams(vp); - foreach (ViewerWindow* window, windows_) { - window->display_widget()->SetVideoParams(vp); + foreach (ViewerDisplayWidget *dw, playback_devices_) { + dw->SetVideoParams(vp); } } diff --git a/app/widget/viewer/viewer.h b/app/widget/viewer/viewer.h index 9d5ef1994..e8ef472c9 100644 --- a/app/widget/viewer/viewer.h +++ b/app/widget/viewer/viewer.h @@ -37,8 +37,6 @@ #include "render/previewautocacher.h" #include "threading/threadticketwatcher.h" #include "viewerdisplay.h" -#include "viewerplaybacktimer.h" -#include "viewerqueue.h" #include "viewersizer.h" #include "viewerwindow.h" #include "widget/playbackcontrols/playbackcontrols.h" @@ -183,7 +181,7 @@ private: bool ViewerMightBeAStill(); - void SetDisplayImage(QVariant frame, bool main_only = false); + void SetDisplayImage(QVariant frame); void RequestNextFrameForQueue(bool prioritize = false, bool increment = true); @@ -193,8 +191,6 @@ private: int DeterminePlaybackQueueSize(); - void PopOldestFrameFromPlaybackQueue(); - static FramePtr DecodeCachedImage(const QString &cache_path, const QByteArray &hash, const rational& time); static void DecodeCachedImage(RenderTicketPtr ticket, const QString &cache_path, const QByteArray &hash, const rational& time); @@ -231,11 +227,10 @@ private: ViewerDisplayWidget* context_menu_widget_; - ViewerPlaybackTimer playback_timer_; QTimer playback_backup_timer_; - ViewerQueue playback_queue_; int64_t playback_queue_next_frame_; + QVector playback_devices_; bool prequeuing_video_; int prequeuing_audio_; @@ -245,6 +240,7 @@ private: rational last_length_; int prequeue_length_; + int prequeue_count_; PreviewAutoCacher auto_cacher_; diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index f90ea032a..e8f8dfe36 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -313,16 +313,20 @@ void ViewerDisplayWidget::dropEvent(QDropEvent *event) void ViewerDisplayWidget::showEvent(QShowEvent *event) { - emit VisibilityChanged(true); - super::showEvent(event); + + if (isVisible()) { + emit VisibilityChanged(true); + } } void ViewerDisplayWidget::hideEvent(QHideEvent *event) { - emit VisibilityChanged(false); - super::hideEvent(event); + + if (!isVisible()) { + emit VisibilityChanged(false); + } } void ViewerDisplayWidget::OnPaint() @@ -602,4 +606,73 @@ void ViewerDisplayWidget::SetShowFPS(bool e) update(); } +void ViewerDisplayWidget::Play(const int64_t &start_timestamp, const int &playback_speed, const rational &timebase) +{ + playback_timebase_ = timebase; + + timer_.Start(start_timestamp, playback_speed, timebase.toDouble()); + + connect(this, &ViewerDisplayWidget::frameSwapped, this, &ViewerDisplayWidget::UpdateFromQueue); + + update(); +} + +void ViewerDisplayWidget::Pause() +{ + disconnect(this, &ViewerDisplayWidget::frameSwapped, this, &ViewerDisplayWidget::UpdateFromQueue); + + queue_.clear(); +} + +void ViewerDisplayWidget::UpdateFromQueue() +{ + int64_t t = timer_.GetTimestampNow(); + + rational time = Timecode::timestamp_to_time(t, playback_timebase_); + + bool popped = false; + + if (queue_.empty()) { + //ForceRequeueFromCurrentTime(); + } else { + while (!queue_.empty()) { + const ViewerPlaybackFrame& pf = queue_.front(); + + if (pf.timestamp == time) { + + // Frame was in queue, no need to decode anything + SetImage(pf.frame); + return; + + } else if (pf.timestamp > time) { + + // The next frame in the queue is too new, so just do a regular update. Either the + // frame we want will arrive in time, or we'll just have to skip it. + break; + + } else { + + queue_.pop_front(); + + if (popped) { + // We've already popped a frame in this loop, meaning a frame has been skipped + IncrementSkippedFrames(); + } else { + // Shown a frame and progressed to the next one + IncrementFrameCount(); + popped = true; + } + + if (queue_.empty()) { + //ForceRequeueFromCurrentTime(); + break; + } + + } + } + } + + update(); +} + } diff --git a/app/widget/viewer/viewerdisplay.h b/app/widget/viewer/viewerdisplay.h index c9d05ef23..71f1b1d8e 100644 --- a/app/widget/viewer/viewerdisplay.h +++ b/app/widget/viewer/viewerdisplay.h @@ -28,6 +28,8 @@ #include "node/node.h" #include "render/color.h" #include "tool/tool.h" +#include "viewerplaybacktimer.h" +#include "viewerqueue.h" #include "viewersafemargininfo.h" #include "widget/manageddisplay/manageddisplay.h" #include "widget/timetarget/timetarget.h" @@ -107,6 +109,20 @@ public: return texture_; } + void Play(const int64_t &start_timestamp, const int &playback_speed, const rational &timebase); + + void Pause(); + + ViewerQueue* queue() + { + return &queue_; + } + + ViewerPlaybackTimer *timer() + { + return &timer_; + } + public slots: /** * @brief Set the transformation matrix to draw with @@ -210,6 +226,8 @@ protected: virtual void hideEvent(QHideEvent* event) override; + //virtual void closeEvent(QCloseEvent* event) override; + protected slots: /** * @brief Paint function to display the texture (received in SetTexture()) on screen. @@ -334,9 +352,18 @@ private: PushMode push_mode_; + // Playback + ViewerQueue queue_; + + ViewerPlaybackTimer timer_; + + rational playback_timebase_; + private slots: void EmitColorAtCursor(QMouseEvent* e); + void UpdateFromQueue(); + }; } diff --git a/app/widget/viewer/viewerqueue.h b/app/widget/viewer/viewerqueue.h index d3aa65843..1d5c5df60 100644 --- a/app/widget/viewer/viewerqueue.h +++ b/app/widget/viewer/viewerqueue.h @@ -50,6 +50,16 @@ public: } } + void PurgeBefore(const rational &time, int playback_speed) + { + int popped = 0; + while (!this->empty() && this->front().timestamp < time) { + popped++; + this->pop_front(); + } + if (popped > 0) qDebug() << "Purged" << popped; + } + }; } diff --git a/app/widget/viewer/viewerwindow.cpp b/app/widget/viewer/viewerwindow.cpp index eb4ba0531..1d9c00460 100644 --- a/app/widget/viewer/viewerwindow.cpp +++ b/app/widget/viewer/viewerwindow.cpp @@ -68,24 +68,6 @@ void ViewerWindow::SetPixelAspectRatio(const rational &pixel_aspect) UpdateMatrix(); } -void ViewerWindow::Play(const int64_t& start_timestamp, const int& playback_speed, const rational &timebase) -{ - timer_.Start(start_timestamp, playback_speed, timebase.toDouble()); - - playback_timebase_ = timebase; - - connect(display_widget_, &ViewerDisplayWidget::frameSwapped, this, &ViewerWindow::UpdateFromQueue); - - display_widget_->update(); -} - -void ViewerWindow::Pause() -{ - disconnect(display_widget_, &ViewerDisplayWidget::frameSwapped, this, &ViewerWindow::UpdateFromQueue); - - queue_.clear(); -} - void ViewerWindow::keyPressEvent(QKeyEvent *e) { QWidget::keyPressEvent(e); @@ -102,27 +84,6 @@ void ViewerWindow::closeEvent(QCloseEvent *e) deleteLater(); } -void ViewerWindow::UpdateFromQueue() -{ - int64_t t = timer_.GetTimestampNow(); - - rational time = Timecode::timestamp_to_time(t, playback_timebase_); - - while (!queue_.empty()) { - const ViewerPlaybackFrame& pf = queue_.front(); - - if (pf.timestamp == time) { - // Frame was in queue, no need to decode anything - display_widget_->SetImage(pf.frame); - return; - } else { - queue_.pop_front(); - } - } - - display_widget_->update(); -} - void ViewerWindow::UpdateMatrix() { // Set GL widget matrix to maintain this texture's aspect ratio diff --git a/app/widget/viewer/viewerwindow.h b/app/widget/viewer/viewerwindow.h index daec23338..0810cb1e2 100644 --- a/app/widget/viewer/viewerwindow.h +++ b/app/widget/viewer/viewerwindow.h @@ -24,8 +24,6 @@ #include #include "viewerdisplay.h" -#include "viewerplaybacktimer.h" -#include "viewerqueue.h" namespace olive { @@ -54,37 +52,20 @@ public: */ void SetPixelAspectRatio(const rational& pixel_aspect); - ViewerQueue* queue() { - return &queue_; - } - - void Play(const int64_t &start_timestamp, const int &playback_speed, const rational &timebase); - - void Pause(); - protected: virtual void keyPressEvent(QKeyEvent* e) override; virtual void closeEvent(QCloseEvent* e) override; -private slots: - void UpdateFromQueue(); - private: void UpdateMatrix(); - ViewerDisplayWidget* display_widget_; - - ViewerQueue queue_; - - ViewerPlaybackTimer timer_; - - rational playback_timebase_; - int width_; int height_; + ViewerDisplayWidget* display_widget_; + rational pixel_aspect_; };