reworked viewer timers
This commit is contained in:
@@ -101,11 +101,4 @@ void ViewerPanelBase::SetViewerWidget(ViewerWidget *vw)
|
||||
SetTimeBasedWidget(vw);
|
||||
}
|
||||
|
||||
void ViewerPanelBase::closeEvent(QCloseEvent *e)
|
||||
{
|
||||
static_cast<ViewerWidget*>(GetTimeBasedWidget())->Pause();
|
||||
|
||||
TimeBasedPanel::closeEvent(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -88,8 +88,6 @@ signals:
|
||||
protected:
|
||||
void SetViewerWidget(ViewerWidget *vw);
|
||||
|
||||
virtual void closeEvent(QCloseEvent* e) override;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+64
-142
@@ -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<ViewerWindow*>(sender())));
|
||||
ViewerWindow *vw = static_cast<ViewerWindow*>(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<rational>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ViewerDisplayWidget*> 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_;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#include <QWidget>
|
||||
|
||||
#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_;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user