cache: fixed audio with new system

This commit is contained in:
itsmattkc
2020-05-18 17:16:28 +10:00
parent 127ebbe359
commit 558773538d
7 changed files with 121 additions and 63 deletions
-1
View File
@@ -192,7 +192,6 @@ void TrackList::TrackConnected(NodeEdgePtr edge)
connect(connected_track, &TrackOutput::TrackLengthChanged, this, &TrackList::UpdateTotalLength);
connect(connected_track, &TrackOutput::TrackHeightChanged, this, &TrackList::TrackHeightChangedSlot);
qDebug() << "Setting track type" << connected_track << type_;
connected_track->set_track_type(type_);
emit TrackListChanged();
-1
View File
@@ -60,7 +60,6 @@ void AudioPlaybackCache::SetParameters(const AudioRenderingParams &params)
void AudioPlaybackCache::WritePCM(const TimeRange &range, SampleBufferPtr samples)
{
QFile f(filename_);
qDebug() << "Writing PCM to" << filename_;
if (f.open(QFile::ReadWrite)) {
qint64 start_offset = params_.time_to_bytes(range.in());
qint64 max_len = params_.time_to_bytes(range.out());
+91 -33
View File
@@ -34,8 +34,7 @@ OLIVE_NAMESPACE_ENTER
RenderBackend::RenderBackend(QObject *parent) :
QObject(parent),
viewer_node_(nullptr),
video_instance_queuer_(0),
audio_instance_queuer_(0),
audio_enabled_(true),
divider_(1),
render_mode_(RenderMode::kOnline),
pix_fmt_(PixelFormat::PIX_FMT_RGBA32F),
@@ -62,9 +61,10 @@ void RenderBackend::SetViewerNode(ViewerOutput *viewer_node)
CancelQueue();
// Delete all of our copied nodes
foreach (RenderWorker* instance, video_instance_pool_) {
instance->Close();
}
hash_pool_.Close();
video_pool_.Close();
audio_pool_.Close();
queued_audio_.clear();
disconnect(viewer_node_,
&ViewerOutput::GraphChangedFrom,
@@ -82,32 +82,42 @@ void RenderBackend::SetViewerNode(ViewerOutput *viewer_node)
if (viewer_node_) {
// Initiate instances with new node
foreach (RenderWorker* instance, video_instance_pool_) {
instance->Init(viewer_node_);
}
hash_pool_.Init(viewer_node_);
video_pool_.Init(viewer_node_);
audio_pool_.Init(viewer_node_);
connect(viewer_node_,
&ViewerOutput::GraphChangedFrom,
this,
&RenderBackend::NodeGraphChanged);
connect(viewer_node_->audio_playback_cache(),
&AudioPlaybackCache::Invalidated,
this,
&RenderBackend::AudioInvalidated);
if (audio_enabled_) {
// Listen for audio invalidation signals
connect(viewer_node_->audio_playback_cache(),
&AudioPlaybackCache::Invalidated,
this,
&RenderBackend::AudioInvalidated);
// Start caching audio
foreach (const TimeRange& r, viewer_node_->audio_playback_cache()->GetInvalidatedRanges()) {
AudioInvalidated(r);
}
}
}
}
void RenderBackend::CancelQueue()
{
// FIXME: Implement something better than this...
video_thread_pool_.waitForDone();
video_pool_.threads.waitForDone();
audio_pool_.threads.waitForDone();
hash_pool_.threads.waitForDone();
}
QFuture<QByteArray> RenderBackend::Hash(const rational &time, bool block_for_update)
{
return QtConcurrent::run(&video_thread_pool_,
GetInstanceFromPool(video_instance_pool_, video_thread_pool_, video_instance_queuer_),
return QtConcurrent::run(&hash_pool_.threads,
GetInstanceFromPool(hash_pool_),
&RenderWorker::Hash,
time,
block_for_update);
@@ -116,11 +126,11 @@ QFuture<QByteArray> RenderBackend::Hash(const rational &time, bool block_for_upd
QFuture<FramePtr> RenderBackend::RenderFrame(const rational &time, bool clear_queue, bool block_for_update)
{
if (clear_queue) {
video_thread_pool_.clear();
video_pool_.threads.clear();
}
return QtConcurrent::run(&video_thread_pool_,
GetInstanceFromPool(video_instance_pool_, video_thread_pool_, video_instance_queuer_),
return QtConcurrent::run(&video_pool_.threads,
GetInstanceFromPool(video_pool_),
&RenderWorker::RenderFrame,
time,
block_for_update);
@@ -151,11 +161,23 @@ void RenderBackend::SetVideoDownloadMatrix(const QMatrix4x4 &mat)
video_download_matrix_ = mat;
}
void RenderBackend::SetAudioEnabled(bool e)
{
audio_enabled_ = e;
}
void RenderBackend::WorkerStartedRenderingAudio(const TimeRange &r)
{
queued_audio_lock_.lock();
queued_audio_.RemoveTimeRange(r);
queued_audio_lock_.unlock();
}
void RenderBackend::NodeGraphChanged(NodeInput *source)
{
foreach (RenderWorker* worker, video_instance_pool_) {
worker->Queue(source);
}
video_pool_.Queue(source);
audio_pool_.Queue(source);
hash_pool_.Queue(source);
}
void RenderBackend::UpdateInstance(RenderWorker *instance)
@@ -171,8 +193,9 @@ void RenderBackend::Close()
{
CancelQueue();
qDeleteAll(video_instance_pool_);
video_instance_pool_.clear();
video_pool_.Destroy();
audio_pool_.Destroy();
hash_pool_.Destroy();
}
VideoRenderingParams RenderBackend::video_params() const
@@ -185,11 +208,11 @@ AudioRenderingParams RenderBackend::audio_params() const
return AudioRenderingParams(viewer_node_->audio_params(), sample_fmt_);
}
RenderWorker *RenderBackend::GetInstanceFromPool(QVector<RenderWorker *> &worker_pool, QThreadPool &thread_pool, int &instance_queuer)
RenderWorker *RenderBackend::GetInstanceFromPool(RenderPool& pool)
{
RenderWorker* instance = nullptr;
foreach (RenderWorker* worker, worker_pool) {
foreach (RenderWorker* worker, pool.instances) {
if (worker->IsAvailable()) {
instance = worker;
break;
@@ -197,10 +220,10 @@ RenderWorker *RenderBackend::GetInstanceFromPool(QVector<RenderWorker *> &worker
}
if (!instance) {
if (worker_pool.size() < thread_pool.maxThreadCount()) {
if (pool.instances.size() < pool.threads.maxThreadCount()) {
// Can create another instance
instance = CreateNewWorker();
worker_pool.append(instance);
pool.instances.append(instance);
if (viewer_node_) {
instance->Init(viewer_node_);
@@ -212,8 +235,8 @@ RenderWorker *RenderBackend::GetInstanceFromPool(QVector<RenderWorker *> &worker
connect(instance, &RenderWorker::AudioConformUnavailable,
this, &RenderBackend::AudioConformUnavailable, Qt::QueuedConnection);
} else {
instance = worker_pool.at(instance_queuer % worker_pool.size());
instance_queuer++;
instance = pool.instances.at(pool.queuer % pool.instances.size());
pool.queuer++;
}
}
@@ -337,13 +360,23 @@ void RenderBackend::AudioInvalidated(const TimeRange& r)
}
}
// FIXME: Split into chunks for multithreading
{
QMutexLocker locker(&queued_audio_lock_);
if (queued_audio_.ContainsTimeRange(r)) {
return;
}
queued_audio_.InsertTimeRange(r);
}
QFutureWatcher<SampleBufferPtr>* watcher = new QFutureWatcher<SampleBufferPtr>();
connect(watcher, &QFutureWatcher<SampleBufferPtr>::finished, this, &RenderBackend::AudioRendered);
audio_jobs_.insert(watcher, r);
watcher->setFuture(QtConcurrent::run(&video_thread_pool_,
GetInstanceFromPool(audio_instance_pool_, audio_thread_pool_, audio_instance_queuer_),
watcher->setFuture(QtConcurrent::run(&audio_pool_.threads,
GetInstanceFromPool(audio_pool_),
&RenderWorker::RenderAudio,
r));
}
@@ -356,10 +389,8 @@ void RenderBackend::AudioRendered()
TimeRange r = audio_jobs_.take(watcher);
if (watcher->result()) {
qDebug() << "Received" << watcher->result()->sample_count_per_channel() << "samples";
viewer_node_->audio_playback_cache()->WritePCM(r, watcher->result());
} else {
qDebug() << "Received null";
viewer_node_->audio_playback_cache()->WriteSilence(r);
}
}
@@ -379,4 +410,31 @@ bool RenderBackend::ConformWaitInfo::operator==(const RenderBackend::ConformWait
&& rhs.affected_range == affected_range;
}
void RenderBackend::RenderPool::Init(ViewerOutput* v)
{
foreach (RenderWorker* instance, instances) {
instance->Init(v);
}
}
void RenderBackend::RenderPool::Queue(NodeInput *input)
{
foreach (RenderWorker* worker, instances) {
worker->Queue(input);
}
}
void RenderBackend::RenderPool::Destroy()
{
qDeleteAll(instances);
instances.clear();
}
void RenderBackend::RenderPool::Close()
{
foreach (RenderWorker* worker, instances) {
worker->Close();
}
}
OLIVE_NAMESPACE_EXIT
+22 -9
View File
@@ -64,6 +64,10 @@ public:
void SetVideoDownloadMatrix(const QMatrix4x4& mat);
void SetAudioEnabled(bool e);
void WorkerStartedRenderingAudio(const TimeRange& r);
public slots:
void NodeGraphChanged(NodeInput *source);
@@ -79,22 +83,31 @@ protected:
AudioRenderingParams audio_params() const;
private:
RenderWorker *GetInstanceFromPool(QVector<RenderWorker*>& worker_pool,
QThreadPool& thread_pool,
int& instance_queuer);
struct RenderPool {
QVector<RenderWorker*> instances;
int queuer;
QThreadPool threads;
void Init(ViewerOutput *v);
void Queue(NodeInput* input);
void Close();
void Destroy();
};
RenderWorker *GetInstanceFromPool(RenderPool &pool);
ViewerOutput* viewer_node_;
RenderCancelDialog* cancel_dialog_;
QVector<RenderWorker*> video_instance_pool_;
QVector<RenderWorker*> audio_instance_pool_;
RenderPool video_pool_;
RenderPool audio_pool_;
RenderPool hash_pool_;
QThreadPool video_thread_pool_;
QThreadPool audio_thread_pool_;
QMutex queued_audio_lock_;
TimeRangeList queued_audio_;
int video_instance_queuer_;
int audio_instance_queuer_;
bool audio_enabled_;
// VIDEO MEMBERS
int divider_;
+2 -14
View File
@@ -107,17 +107,12 @@ SampleBufferPtr RenderWorker::RenderAudio(const TimeRange &range)
QMutexLocker locker(&lock_);
parent_->WorkerStartedRenderingAudio(range);
UpdateData(true);
audio_render_time_ = range;
qDebug() << "Audio deps:";
QList<Node*> d = viewer_->samples_input()->GetDependencies();
foreach (Node* n, d) {
qDebug() << " " << n;
}
NodeValueTable table = ProcessInput(viewer_->samples_input(), range);
QVariant samples = table.Get(NodeParam::kSamples);
@@ -314,8 +309,6 @@ void RenderWorker::ProcessNodeEvent(const Node *node, const TimeRange &range, No
void RenderWorker::FootageProcessingEvent(StreamPtr stream, const TimeRange &input_time, NodeValueTable *table)
{
qDebug() << "Stream type" << stream->type();
if (stream->type() == Stream::kVideo || stream->type() == Stream::kImage) {
ImageStreamPtr video_stream = std::static_pointer_cast<ImageStream>(stream);
@@ -355,7 +348,6 @@ void RenderWorker::FootageProcessingEvent(StreamPtr stream, const TimeRange &inp
} else if (stream->type() == Stream::kAudio) {
qDebug() << "Hello!";
table->Push(GetDataFromStream(stream, input_time));
}
@@ -369,18 +361,14 @@ NodeValue RenderWorker::GetDataFromStream(StreamPtr stream, const TimeRange &inp
if (stream->type() == Stream::kVideo || stream->type() == Stream::kImage) {
return FrameToTexture(decoder, stream, input_time);
} else if (stream->type() == Stream::kAudio) {
qDebug() << "Decoding audio!";
if (decoder->HasConformedVersion(audio_params())) {
qDebug() << " Retrieving audio!";
SampleBufferPtr frame = decoder->RetrieveAudio(input_time.in(), input_time.length(),
audio_params());
if (frame) {
qDebug() << " Returning audio!";
return NodeValue(NodeParam::kSamples, QVariant::fromValue(frame));
}
} else {
qDebug() << " Conform doesn't exist! AAAAA";
emit AudioConformUnavailable(decoder->stream(), audio_render_time_,
input_time.out(), audio_params());
}
+1
View File
@@ -63,6 +63,7 @@ void CacheTask::Action()
RenderMode::Mode mode = RenderMode::kOffline;
PixelFormat::Format format = PixelFormat::instance()->GetConfiguredFormatForMode(mode);
backend.SetAudioEnabled(false);
backend.SetViewerNode(viewer_);
backend.SetPixelFormat(format);
backend.SetMode(mode);
+5 -5
View File
@@ -433,6 +433,11 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
playback_speed_ = speed;
play_in_to_out_only_ = in_to_out_only;
int64_t start_time = ruler()->GetTime();
playback_queue_next_frame_ = start_time;
FillPlaybackQueue();
QString audio_fn = GetConnectedNode()->audio_playback_cache()->GetCacheFilename();
if (!audio_fn.isEmpty()) {
AudioManager::instance()->SetOutputParams(GetConnectedNode()->audio_playback_cache()->GetParameters());
@@ -441,11 +446,6 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
playback_speed_);
}
int64_t start_time = ruler()->GetTime();
playback_queue_next_frame_ = start_time;
FillPlaybackQueue();
playback_timer_.Start(start_time, playback_speed_, timebase_dbl());
foreach (ViewerWindow* window, windows_) {