proxy: isolate proxies from export renders and improve proxy workflow
- FootageJob::should_use_proxy() centralizes the proxy decision; worker pre-decode now honors the render mode so exports always decode the original media (previously every frame was pre-decoded from proxies) - global Tools > Use Proxy Media toggle with footage invalidation - ffmpeg -progress parsing for real percentage feedback while generating - divider mode (1/2, 1/4, 1/8 of source resolution) with UI, proxy filename tags and per-footage persistence (pdivider) - Media Offline warning slat rendered for missing footage - regression tests: export isolation, relink invalidation, offline slat, progress parsing, divider arguments
This commit is contained in:
@@ -22,7 +22,10 @@
|
||||
#ifndef OAK_FOOTAGEJOB_H
|
||||
#define OAK_FOOTAGEJOB_H
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "node/project/footage/footage.h"
|
||||
#include "render/rendermodes.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
@@ -85,6 +88,20 @@ public:
|
||||
has_proxy_ = !filename.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Whether decoding for the given render mode should use the proxy
|
||||
*
|
||||
* Proxies are a preview accelerator only: offline (realtime preview)
|
||||
* renders may decode from them, online (export/master) renders must
|
||||
* always decode the original media. The proxy file must also still
|
||||
* exist on disk, otherwise decoding falls back to the original.
|
||||
*/
|
||||
bool should_use_proxy(RenderMode::Mode mode) const
|
||||
{
|
||||
return mode == RenderMode::k_offline && has_proxy() &&
|
||||
QFileInfo::exists(proxy_filename_);
|
||||
}
|
||||
|
||||
Track::Type type() const
|
||||
{
|
||||
return type_;
|
||||
|
||||
@@ -530,10 +530,8 @@ void RenderProcessor::process_video_footage(TexturePtr destination,
|
||||
return;
|
||||
}
|
||||
|
||||
const bool use_proxy =
|
||||
static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()) ==
|
||||
RenderMode::k_offline &&
|
||||
stream->has_proxy() && QFileInfo::exists(stream->proxy_filename());
|
||||
const bool use_proxy = stream->should_use_proxy(
|
||||
static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()));
|
||||
const QString decode_filename = use_proxy ? stream->proxy_filename() :
|
||||
stream->filename();
|
||||
const QString decoder_id = use_proxy ? stream->proxy_decoder() :
|
||||
@@ -613,10 +611,8 @@ void RenderProcessor::process_audio_footage(SampleBuffer &destination,
|
||||
|
||||
// Mirror the video path: use the proxy (when enabled, ready, and containing
|
||||
// audio) for offline renders only, never for export
|
||||
const bool use_proxy =
|
||||
static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()) ==
|
||||
RenderMode::k_offline &&
|
||||
stream->has_proxy() && QFileInfo::exists(stream->proxy_filename());
|
||||
const bool use_proxy = stream->should_use_proxy(
|
||||
static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()));
|
||||
const QString decode_filename = use_proxy ? stream->proxy_filename() :
|
||||
stream->filename();
|
||||
const QString decoder_id = use_proxy ? stream->proxy_decoder() :
|
||||
|
||||
@@ -137,16 +137,18 @@ DecoderPtr resolve_decoder_from_cache(DecoderCache *decoder_cache,
|
||||
}
|
||||
|
||||
FramePtr decode_input_frame(DecoderCache *decoder_cache,
|
||||
const FootageInput &input, CancelAtom *cancel)
|
||||
const FootageInput &input, CancelAtom *cancel,
|
||||
RenderMode::Mode mode)
|
||||
{
|
||||
VideoParams stream_data = input.job.video_params();
|
||||
QString filename = input.job.filename();
|
||||
QString decoder_id = input.job.decoder();
|
||||
int stream_index = stream_data.stream_index();
|
||||
|
||||
// Use generated proxy if one is attached to the job. The Footage node only
|
||||
// attaches a proxy when it is enabled, ready, and matches this stream.
|
||||
if (input.job.has_proxy()) {
|
||||
// Use the generated proxy when this render is allowed to (preview only,
|
||||
// never export). The Footage node only attaches a proxy when it is
|
||||
// enabled, ready, and matches this stream.
|
||||
if (input.job.should_use_proxy(mode)) {
|
||||
filename = input.job.proxy_filename();
|
||||
decoder_id = input.job.proxy_decoder();
|
||||
stream_index = input.job.proxy_stream_index();
|
||||
@@ -219,7 +221,8 @@ bool decode_input_frames(DecoderCache *decoder_cache,
|
||||
return false;
|
||||
}
|
||||
|
||||
FramePtr frame = decode_input_frame(decoder_cache, input, cancel);
|
||||
FramePtr frame =
|
||||
decode_input_frame(decoder_cache, input, cancel, params.mode);
|
||||
if (!frame || !frame->is_allocated()) {
|
||||
frames->clear();
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user