diff --git a/app/codec/decoder.h b/app/codec/decoder.h index 061378be0..99fa74428 100644 --- a/app/codec/decoder.h +++ b/app/codec/decoder.h @@ -34,6 +34,7 @@ extern "C" { #include "codec/frame.h" #include "codec/samplebuffer.h" #include "common/rational.h" +#include "node/block/block.h" #include "node/project/footage/footage.h" #include "node/project/footage/footagedescription.h" #include "task/task.h" @@ -85,13 +86,15 @@ public: { public: CodecStream() : - stream_(-1) + stream_(-1), + block_(nullptr) { } - CodecStream(const QString& filename, int stream) : + CodecStream(const QString& filename, int stream, Block *block) : filename_(filename), - stream_(stream) + stream_(stream), + block_(block) { } @@ -125,11 +128,18 @@ public: return stream_; } + Block *block() const + { + return block_; + } + private: QString filename_; int stream_; + Block *block_; + }; /** diff --git a/app/codec/ffmpeg/ffmpegdecoder.cpp b/app/codec/ffmpeg/ffmpegdecoder.cpp index 977f1c251..a2ebad125 100644 --- a/app/codec/ffmpeg/ffmpegdecoder.cpp +++ b/app/codec/ffmpeg/ffmpegdecoder.cpp @@ -63,7 +63,6 @@ FFmpegDecoder::FFmpegDecoder() : native_output_pix_fmt_(VideoParams::kFormatInvalid), working_frame_(nullptr), working_packet_(nullptr), - is_working_(false), cache_at_zero_(false), cache_at_eof_(false) { @@ -750,7 +749,7 @@ AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt * int64_t target_ts = GetTimeInTimebaseUnits(time, instance_.avstream()->time_base, instance_.avstream()->start_time); const int64_t min_seek = -instance_.avstream()->start_time; - int64_t seek_ts = target_ts; + int64_t seek_ts = std::max(min_seek, target_ts - MaximumQueueSize()); bool still_seeking = false; if (time != kAnyTimecode) { @@ -839,7 +838,7 @@ AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt * } else { // Cut down to thread count - 1 before we acquire a new frame - if (cached_frames_.size() == size_t(QThread::idealThreadCount())) { + if (cached_frames_.size() == size_t(MaximumQueueSize())) { RemoveFirstFrame(); } @@ -1040,6 +1039,11 @@ void FFmpegDecoder::RemoveFirstFrame() cache_at_zero_ = false; } +int FFmpegDecoder::MaximumQueueSize() +{ + return QThread::idealThreadCount(); +} + FFmpegDecoder::Instance::Instance() : fmt_ctx_(nullptr), codec_ctx_(nullptr), diff --git a/app/codec/ffmpeg/ffmpegdecoder.h b/app/codec/ffmpeg/ffmpegdecoder.h index 80c46fb1f..4e51f496f 100644 --- a/app/codec/ffmpeg/ffmpegdecoder.h +++ b/app/codec/ffmpeg/ffmpegdecoder.h @@ -155,6 +155,8 @@ private: void RemoveFirstFrame(); + static int MaximumQueueSize(); + RetrieveVideoParams filter_params_; AVFilterGraph* filter_graph_; AVFilterContext* buffersrc_ctx_; @@ -171,9 +173,6 @@ private: std::list cached_frames_; - bool is_working_; - QMutex is_working_mutex_; - bool cache_at_zero_; bool cache_at_eof_; diff --git a/app/render/rendercache.h b/app/render/rendercache.h index 114244fb8..77a56780d 100644 --- a/app/render/rendercache.h +++ b/app/render/rendercache.h @@ -39,15 +39,10 @@ private: }; -struct DecoderPair { - DecoderPair() - { - decoder = nullptr; - last_modified = 0; - } - - DecoderPtr decoder; - qint64 last_modified; +struct DecoderPair +{ + DecoderPtr decoder = nullptr; + qint64 last_modified = 0; }; using DecoderCache = RenderCache; diff --git a/app/render/renderer.cpp b/app/render/renderer.cpp index 80683c285..b66fd6ca8 100644 --- a/app/render/renderer.cpp +++ b/app/render/renderer.cpp @@ -72,8 +72,21 @@ TexturePtr Renderer::InterlaceTexture(TexturePtr top, TexturePtr bottom, const V return output; } +QVariant Renderer::GetDefaultShader() +{ + if (default_shader_.isNull()) { + default_shader_ = CreateNativeShader(ShaderCode(QString(), QString())); + } + + return default_shader_; +} + void Renderer::Destroy() { + if (!default_shader_.isNull()) { + DestroyNativeShader(default_shader_); + } + color_cache_.clear(); if (!interlace_texture_.isNull()) { diff --git a/app/render/renderer.h b/app/render/renderer.h index 749d777cf..839be32cf 100644 --- a/app/render/renderer.h +++ b/app/render/renderer.h @@ -76,6 +76,8 @@ public: TexturePtr InterlaceTexture(TexturePtr top, TexturePtr bottom, const VideoParams ¶ms); + QVariant GetDefaultShader(); + void Destroy(); virtual void PostDestroy() = 0; @@ -134,6 +136,8 @@ private: QMutex color_cache_mutex_; + QVariant default_shader_; + QVariant interlace_texture_; }; diff --git a/app/render/rendermanager.cpp b/app/render/rendermanager.cpp index c34b050d8..9710aa626 100644 --- a/app/render/rendermanager.cpp +++ b/app/render/rendermanager.cpp @@ -54,7 +54,6 @@ RenderManager::RenderManager(QObject *parent) : decoder_cache_ = new DecoderCache(); shader_cache_ = new ShaderCache(); - default_shader_ = context_->CreateNativeShader(ShaderCode(QString(), QString())); } else { qCritical() << "Tried to initialize unknown graphics backend"; context_ = nullptr; @@ -65,8 +64,6 @@ RenderManager::RenderManager(QObject *parent) : RenderManager::~RenderManager() { if (context_) { - context_->DestroyNativeShader(default_shader_); - delete shader_cache_; delete decoder_cache_; @@ -157,7 +154,7 @@ void RenderManager::RunTicket(RenderTicketPtr ticket) const return; } - RenderProcessor::Process(ticket, context_, decoder_cache_, shader_cache_, default_shader_); + RenderProcessor::Process(ticket, context_, decoder_cache_, shader_cache_); } } diff --git a/app/render/rendermanager.h b/app/render/rendermanager.h index 8753f7c90..2cf6b22a7 100644 --- a/app/render/rendermanager.h +++ b/app/render/rendermanager.h @@ -130,8 +130,6 @@ private: ShaderCache* shader_cache_; - QVariant default_shader_; - }; } diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp index 37e11a66a..31fc78ec6 100644 --- a/app/render/renderprocessor.cpp +++ b/app/render/renderprocessor.cpp @@ -35,12 +35,11 @@ namespace olive { #define super NodeTraverser -RenderProcessor::RenderProcessor(RenderTicketPtr ticket, Renderer *render_ctx, DecoderCache* decoder_cache, ShaderCache *shader_cache, QVariant default_shader) : +RenderProcessor::RenderProcessor(RenderTicketPtr ticket, Renderer *render_ctx, DecoderCache* decoder_cache, ShaderCache *shader_cache) : ticket_(ticket), render_ctx_(render_ctx), decoder_cache_(decoder_cache), - shader_cache_(shader_cache), - default_shader_(default_shader) + shader_cache_(shader_cache) { } @@ -115,7 +114,7 @@ FramePtr RenderProcessor::GenerateFrame(TexturePtr texture, const rational& time job.Insert(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(texture))); job.Insert(QStringLiteral("ove_mvpmat"), NodeValue(NodeValue::kMatrix, matrix)); - render_ctx_->BlitToTexture(default_shader_, job, blit_tex.get()); + render_ctx_->BlitToTexture(render_ctx_->GetDefaultShader(), job, blit_tex.get()); } // Replace texture that we're going to download in the next step @@ -269,9 +268,9 @@ DecoderPtr RenderProcessor::ResolveDecoderFromInput(const QString& decoder_id, c return decoder.decoder; } -void RenderProcessor::Process(RenderTicketPtr ticket, Renderer *render_ctx, DecoderCache *decoder_cache, ShaderCache *shader_cache, QVariant default_shader) +void RenderProcessor::Process(RenderTicketPtr ticket, Renderer *render_ctx, DecoderCache *decoder_cache, ShaderCache *shader_cache) { - RenderProcessor p(ticket, render_ctx, decoder_cache, shader_cache, default_shader); + RenderProcessor p(ticket, render_ctx, decoder_cache, shader_cache); p.Run(); } diff --git a/app/render/renderprocessor.h b/app/render/renderprocessor.h index 1fb6ea23f..f0ef31227 100644 --- a/app/render/renderprocessor.h +++ b/app/render/renderprocessor.h @@ -32,7 +32,7 @@ namespace olive { class RenderProcessor : public NodeTraverser { public: - static void Process(RenderTicketPtr ticket, Renderer* render_ctx, DecoderCache* decoder_cache, ShaderCache* shader_cache, QVariant default_shader); + static void Process(RenderTicketPtr ticket, Renderer* render_ctx, DecoderCache* decoder_cache, ShaderCache* shader_cache); struct RenderedWaveform { const ClipBlock* block; @@ -71,7 +71,7 @@ protected: virtual void ConvertToReferenceSpace(TexturePtr destination, TexturePtr source, const QString &input_cs) override; private: - RenderProcessor(RenderTicketPtr ticket, Renderer* render_ctx, DecoderCache* decoder_cache, ShaderCache* shader_cache, QVariant default_shader); + RenderProcessor(RenderTicketPtr ticket, Renderer* render_ctx, DecoderCache* decoder_cache, ShaderCache* shader_cache); TexturePtr GenerateTexture(const rational& time, const rational& frame_length); @@ -89,8 +89,6 @@ private: ShaderCache* shader_cache_; - QVariant default_shader_; - }; } diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index 35eb765d0..b5726864c 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -709,7 +709,7 @@ void ViewerWidget::UpdateTextureFromNode() ClearVideoAutoCacherQueue(); } - watcher->SetTicket(GetFrame(time, RenderTicketPriority::kHigh)); + watcher->SetTicket(GetFrame(time, RenderTicketPriority::kNormal)); } else { // There is definitely no frame here, we can immediately flip to showing nothing nonqueue_watchers_.clear(); @@ -762,7 +762,7 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only) playback_speed_ = speed; play_in_to_out_only_ = in_to_out_only; - playback_queue_next_frame_ = GetTimestamp(); + playback_queue_next_frame_ = GetTimestamp() + playback_speed_; controls_->ShowPauseButton(); @@ -776,18 +776,10 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only) 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 - - playback_queue_next_frame_ += playback_speed_ * prequeue_length_; - int64_t temp = playback_queue_next_frame_; - for (int i=0; i