reworked viewer timers

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