export: fixed bug where null frames never got signalled and hung exporting

This commit is contained in:
itsmattkc
2020-04-23 03:02:04 +10:00
parent 8f9c056419
commit 61e3641bcc
6 changed files with 33 additions and 14 deletions
+2 -2
View File
@@ -173,10 +173,10 @@ void Encoder::Open()
}
}
void Encoder::WriteFrame(FramePtr frame)
void Encoder::WriteFrame(FramePtr frame, rational time)
{
if (open_) {
WriteInternal(frame);
WriteInternal(frame, time);
}
}
+2 -2
View File
@@ -103,7 +103,7 @@ public:
public slots:
void Open();
void WriteFrame(OLIVE_NAMESPACE::FramePtr frame);
void WriteFrame(OLIVE_NAMESPACE::FramePtr frame, OLIVE_NAMESPACE::rational time);
virtual void WriteAudio(OLIVE_NAMESPACE::AudioRenderingParams pcm_info, const QString& pcm_filename, OLIVE_NAMESPACE::TimeRange range) = 0;
void Close();
@@ -117,7 +117,7 @@ signals:
protected:
virtual bool OpenInternal() = 0;
virtual void WriteInternal(FramePtr frame) = 0;
virtual void WriteInternal(FramePtr frame, rational time) = 0;
virtual void CloseInternal() = 0;
bool IsOpen() const;
+2 -2
View File
@@ -228,7 +228,7 @@ bool FFmpegEncoder::OpenInternal()
return true;
}
void FFmpegEncoder::WriteInternal(FramePtr frame)
void FFmpegEncoder::WriteInternal(FramePtr frame, rational time)
{
AVFrame* encoded_frame = av_frame_alloc();
@@ -267,7 +267,7 @@ void FFmpegEncoder::WriteInternal(FramePtr frame)
goto fail;
}
encoded_frame->pts = qRound(frame->timestamp().toDouble() / av_q2d(video_codec_ctx_->time_base));
encoded_frame->pts = qRound64(time.toDouble() / av_q2d(video_codec_ctx_->time_base));
WriteAVFrame(encoded_frame, video_codec_ctx_, video_stream_);
+1 -1
View File
@@ -43,7 +43,7 @@ public slots:
protected:
virtual bool OpenInternal() override;
virtual void WriteInternal(FramePtr frame) override;
virtual void WriteInternal(FramePtr frame, rational time) override;
virtual void CloseInternal() override;
private:
+20 -5
View File
@@ -87,12 +87,14 @@ void Exporter::Cancel()
{
if (video_backend_) {
video_backend_->CancelQueue();
video_backend_->Close();
video_backend_->deleteLater();
video_backend_ = nullptr;
}
if (audio_backend_) {
audio_backend_->CancelQueue();
audio_backend_->Close();
audio_backend_->deleteLater();
audio_backend_ = nullptr;
}
@@ -150,6 +152,7 @@ void Exporter::ExportSucceeded()
}
if (video_backend_) {
video_backend_->Close();
video_backend_->deleteLater();
video_backend_ = nullptr;
}
@@ -185,14 +188,12 @@ void Exporter::EncodeFrame()
// Convert color space
color_processor_->ConvertFrame(frame);
// Set frame timestamp
frame->set_timestamp(waiting_for_frame_);
// Encode (may require re-associating alpha?)
QMetaObject::invokeMethod(encoder_,
"WriteFrame",
Qt::QueuedConnection,
OLIVE_NS_ARG(FramePtr, frame));
OLIVE_NS_ARG(FramePtr, frame),
OLIVE_NS_ARG(rational, waiting_for_frame_));
waiting_for_frame_ += params_.video_params().time_base();
@@ -269,7 +270,8 @@ void Exporter::AudioRendered()
Q_ARG(const QString&, cache_fn),
OLIVE_NS_ARG(TimeRange, export_range_));
// We don't need the audio backend anymore
// We don't need the audio backend anymorea
audio_backend_->Close();
audio_backend_->deleteLater();
audio_backend_ = nullptr;
}
@@ -328,6 +330,19 @@ void Exporter::VideoHashesComplete()
connect(video_backend_, &VideoRenderBackend::GeneratedFrame, this, &Exporter::FrameRendered);
// Remove duplicate frames from cache invalidation
const QMap<rational, QByteArray>& time_hash_map = video_backend_->frame_cache()->time_hash_map();
QList<QByteArray> hashes_already_seen;
QMap<rational, QByteArray>::const_iterator i;
for (i=time_hash_map.begin(); i!=time_hash_map.end(); i++) {
if (hashes_already_seen.contains(i.value())) {
ranges.RemoveTimeRange(TimeRange(i.key(), i.key() + params_.video_params().time_base()));
} else {
hashes_already_seen.append(i.value());
}
}
foreach (const TimeRange& range, ranges) {
video_backend_->InvalidateCache(range);
}
+6 -2
View File
@@ -100,7 +100,7 @@ NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path, con
QVariant texture = value.Get(NodeParam::kTexture);
// If we actually have a texture, download it into the disk cache
if (!texture.isNull()) {
if (!texture.isNull() || (!(operating_mode_ & kDownloadOnly))) {
Download(path.in(), texture, frame_cache_->CachePathName(hash, video_params_.format()));
}
@@ -371,7 +371,11 @@ void VideoRenderWorker::Download(const rational& time, QVariant texture, QString
frame->allocate();
TextureToBuffer(texture, frame->width(), frame->height(), frame_gen_mat_, frame->data(), frame->linesize_pixels());
if (texture.isNull()) {
memset(frame->data(), 0, frame->allocated_size());
} else {
TextureToBuffer(texture, frame->width(), frame->height(), frame_gen_mat_, frame->data(), frame->linesize_pixels());
}
emit GeneratedFrame(time, frame);