large scale renderer rework

- Abstracts all OpenGL functionality including UI objects
- Cleans up several rendering codepaths
- Improves threading functionality
- Removes old code and problematic functions
This commit is contained in:
itsmattkc
2020-11-10 11:24:51 +11:00
parent 52b98f3fa3
commit 1d61f89920
42 changed files with 927 additions and 820 deletions
+77 -76
View File
@@ -24,13 +24,16 @@
#include <QVector3D>
#include <QVector4D>
#include "project/project.h"
#include "rendermanager.h"
OLIVE_NAMESPACE_ENTER
RenderProcessor::RenderProcessor(RenderTicketPtr ticket, Renderer *render_ctx) :
RenderProcessor::RenderProcessor(RenderTicketPtr ticket, Renderer *render_ctx, StillImageCache* still_image_cache, DecoderCache* decoder_cache) :
ticket_(ticket),
render_ctx_(render_ctx)
render_ctx_(render_ctx),
still_image_cache_(still_image_cache),
decoder_cache_(decoder_cache)
{
}
@@ -52,21 +55,17 @@ void RenderProcessor::Run()
Renderer::TexturePtr texture = table.Get(NodeParam::kTexture).value<Renderer::TexturePtr>();
VideoParams frame_params = viewer->video_params();
QSize frame_size = ticket_->property("size").value<QSize>();
if (frame_size.isNull()) {
frame_size = QSize(viewer->video_params().effective_width(),
viewer->video_params().effective_height());
if (!frame_size.isNull()) {
frame_params.set_width(frame_size.width());
frame_params.set_height(frame_size.height());
}
FramePtr frame = Frame::Create();
frame->set_timestamp(time);
frame->set_video_params(VideoParams(frame_size.width(),
frame_size.height(),
viewer->video_params().time_base(),
viewer->video_params().format(),
viewer->video_params().pixel_aspect_ratio(),
viewer->video_params().interlacing(),
viewer->video_params().divider()));
frame->set_video_params(frame_params);
frame->allocate();
if (!texture) {
@@ -109,13 +108,38 @@ void RenderProcessor::Run()
// Fail
ticket_->Cancel();
}
this->deleteLater();
}
void RenderProcessor::Process(RenderTicketPtr ticket, Renderer *render_ctx)
DecoderPtr RenderProcessor::ResolveDecoderFromInput(StreamPtr stream)
{
RenderProcessor p(ticket, render_ctx);
if (!stream) {
qWarning() << "Attempted to resolve the decoder of a null stream";
return nullptr;
}
QMutexLocker locker(decoder_cache_->mutex());
DecoderPtr decoder = decoder_cache_->value(stream.get());
if (!decoder) {
// No decoder
decoder = Decoder::CreateFromID(stream->footage()->decoder());
if (decoder->Open(stream)) {
decoder_cache_->insert(stream.get(), decoder);
} else {
qWarning() << "Failed to open decoder for" << stream->footage()->filename()
<< "::" << stream->index();
return nullptr;
}
}
return decoder;
}
void RenderProcessor::Process(RenderTicketPtr ticket, Renderer *render_ctx, StillImageCache *still_image_cache, DecoderCache *decoder_cache)
{
RenderProcessor p(ticket, render_ctx, still_image_cache, decoder_cache);
p.Run();
}
@@ -259,11 +283,24 @@ QVariant RenderProcessor::ProcessVideoFootage(StreamPtr stream, const rational &
if (frame) {
// Return a texture from the derived class
Renderer::TexturePtr unmanaged_texture = render_ctx_->CreateTexture(frame->video_params(), frame->data(), frame->linesize_pixels());
Renderer::TexturePtr unmanaged_texture = render_ctx_->CreateTexture(frame->video_params(),
frame->data(),
frame->linesize_pixels());
Renderer::TexturePtr managed_texture = render_ctx_->TransformColor(unmanaged_texture, )
// We convert to our rendering pixel format, since that will always be float-based which
// is necessary for correct color conversion
VideoParams managed_params = frame->video_params();
managed_params.set_format(video_params.format());
value = render_ctx_->CreateTexture(managed_params);
value = FootageFrameToTexture(stream, frame);
// FIXME: Accessing video_stream->colorspace()
ColorManager* color_manager = video_stream->footage()->project()->color_manager();
ColorProcessorPtr processor = ColorProcessor::Create(color_manager,
video_stream->colorspace(),
ColorTransform(OCIO::ROLE_SCENE_LINEAR));
render_ctx_->BlitColorManaged(processor, unmanaged_texture.get(), value.get());
still_image_cache_->mutex()->lock();
@@ -290,38 +327,10 @@ QVariant RenderProcessor::ProcessAudioFootage(StreamPtr stream, const TimeRange
if (decoder) {
const AudioParams& audio_params = Node::ValueToPtr<ViewerOutput>(ticket_->property("viewer"))->audio_params();
// See if we have a conformed version of this audio
if (!decoder->HasConformedVersion(audio_params)) {
SampleBufferPtr frame = decoder->RetrieveAudio(input_time, audio_params, &IsCancelled());
// If not, the audio needs to be conformed
// For online rendering/export, it's a waste of time to render the audio until we have
// all we need, so we try to handle the conform ourselves
AudioStreamPtr as = std::static_pointer_cast<AudioStream>(stream);
// Check if any other threads are conforming this audio
if (as->try_start_conforming(audio_params)) {
// If not, conform it ourselves
decoder->ConformAudio(&IsCancelled(), audio_params);
} else {
// If another thread is conforming already, hackily try to wait until it's done.
do {
QThread::msleep(1000);
} while (!as->has_conformed_version(audio_params) && !IsCancelled());
}
}
if (decoder->HasConformedVersion(audio_params)) {
SampleBufferPtr frame = decoder->RetrieveAudio(input_time.in(), input_time.length(),
audio_params);
if (frame) {
value = QVariant::fromValue(frame);
}
if (frame) {
value = QVariant::fromValue(frame);
}
}
@@ -330,9 +339,11 @@ QVariant RenderProcessor::ProcessAudioFootage(StreamPtr stream, const TimeRange
QVariant RenderProcessor::ProcessShader(const Node *node, const TimeRange &range, const ShaderJob &job)
{
Q_UNUSED(range)
const VideoParams& video_params = Node::ValueToPtr<ViewerOutput>(ticket_->property("viewer"))->video_params();
render_ctx_->ProcessShader(node, range, job, video_params);
return QVariant::fromValue(render_ctx_->ProcessShader(node, job, video_params));
}
QVariant RenderProcessor::ProcessSamples(const Node *node, const TimeRange &range, const SampleJob &job)
@@ -384,49 +395,39 @@ QVariant RenderProcessor::ProcessFrameGeneration(const Node *node, const Generat
const VideoParams& video_params = Node::ValueToPtr<ViewerOutput>(ticket_->property("viewer"))->video_params();
PixelFormat::Format output_fmt;
if (job.GetAlphaChannelRequired()) {
output_fmt = PixelFormat::GetFormatWithAlphaChannel(video_params.format());
} else {
output_fmt = PixelFormat::GetFormatWithoutAlphaChannel(video_params.format());
}
frame->set_video_params(VideoParams(video_params.width(),
video_params.height(),
video_params.time_base(),
output_fmt,
video_params.pixel_aspect_ratio(),
video_params.interlacing(),
video_params.divider()));
frame->set_video_params(video_params);
frame->allocate();
node->GenerateFrame(frame, job);
Renderer::TexturePtr texture = render_ctx_->CreateTexture(frame->video_params(), frame->data(), frame->linesize_pixels());
Renderer::TexturePtr texture = render_ctx_->CreateTexture(frame->video_params(),
frame->data(),
frame->linesize_pixels());
texture->set_has_meaningful_alpha(job.GetAlphaChannelRequired());
return QVariant::fromValue(texture);
}
QVariant RenderProcessor::GetCachedFrame(const Node *node, const rational &time)
{
if (ticket_->property("mode").value<RenderMode::Mode>() == RenderMode::kOffline
&& !cache_path_.isEmpty()
if (ticket_->property("mode").toInt() == RenderMode::kOffline
&& node->id() == QStringLiteral("org.olivevideoeditor.Olive.videoinput")) {
const VideoParams& video_params = Node::ValueToPtr<ViewerOutput>(ticket_->property("viewer"))->video_params();
QByteArray hash = RenderManager::Hash(node, video_params, time);
FramePtr f = FrameHashCache::LoadCacheFrame(cache_path_, hash);
FramePtr f = FrameHashCache::LoadCacheFrame(ticket_->property("cache").toString(), hash);
if (f) {
// The cached frame won't load with the correct divider by default, so we enforce it here
f->set_video_params(VideoParams(f->width() * video_params.divider(),
f->height() * video_params.divider(),
f->video_params().time_base(),
f->video_params().format(),
f->video_params().pixel_aspect_ratio(),
f->video_params().interlacing(),
video_params.divider()));
VideoParams p = f->video_params();
p.set_width(f->width() * video_params.divider());
p.set_height(f->height() * video_params.divider());
p.set_divider(video_params.divider());
f->set_video_params(p);
Renderer::TexturePtr texture = render_ctx_->CreateTexture(f->video_params(), f->data(), f->linesize_pixels());
return QVariant::fromValue(texture);