cache waveforms at clip level
This commit is contained in:
@@ -406,7 +406,7 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
bool multitrim_enabled = IsClipTrimmable(clicked_item, clips, trim_mode);
|
||||
|
||||
// Create ghosts for trimming
|
||||
foreach (Block* clip_item, clips) {
|
||||
for (Block* clip_item : clips) {
|
||||
if (clip_item != clicked_item
|
||||
&& (!multitrim_enabled || !IsClipTrimmable(clip_item, clips, trim_mode))) {
|
||||
// Either multitrim is disabled or this clip is NOT the earliest/latest in its track. We
|
||||
@@ -481,7 +481,7 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
// I'm only including it to prevent any potentially unintended behavior.
|
||||
if (clips.size() == 1 && !(modifiers & Qt::AltModifier)) {
|
||||
if (ClipBlock *adjacent_clip = dynamic_cast<ClipBlock*>(adjacent)) {
|
||||
foreach (Block *adjacent_link, adjacent_clip->block_links()) {
|
||||
for (Block *adjacent_link : adjacent_clip->block_links()) {
|
||||
adjacent_ghosts.append(AddGhostFromBlock(adjacent_link, flipped_mode));
|
||||
}
|
||||
}
|
||||
@@ -496,7 +496,7 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
// expected to fill the remaining space (no gap needs to be created)
|
||||
ghost->SetData(TimelineViewGhostItem::kTrimIsARollEdit, static_cast<bool>(adjacent));
|
||||
|
||||
foreach (TimelineViewGhostItem *adjacent_ghost, adjacent_ghosts) {
|
||||
for (TimelineViewGhostItem *adjacent_ghost : adjacent_ghosts) {
|
||||
if (adjacent_ghost) {
|
||||
if (treat_trim_as_slide) {
|
||||
// We're sliding a transition rather than a pure trim/roll
|
||||
@@ -699,7 +699,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
// Place the copy instead of the original block
|
||||
block = static_cast<Block*>(Node::CopyNodeInGraph(block, command));
|
||||
if (ClipBlock *new_clip = dynamic_cast<ClipBlock*>(block)) {
|
||||
new_clip->waveform() = static_cast<ClipBlock*>(p.block)->waveform();
|
||||
new_clip->set_waveform(static_cast<ClipBlock*>(p.block)->waveform());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ void BlockSplitCommand::redo()
|
||||
|
||||
if (ClipBlock *new_clip = dynamic_cast<ClipBlock*>(new_block_)) {
|
||||
ClipBlock *old_clip = static_cast<ClipBlock*>(block_);
|
||||
new_clip->waveform() = old_clip->waveform();
|
||||
new_clip->set_waveform(old_clip->waveform());
|
||||
}
|
||||
|
||||
// Determine our new lengths
|
||||
|
||||
@@ -47,6 +47,7 @@ TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) :
|
||||
ghosts_(nullptr),
|
||||
show_beam_cursor_(false),
|
||||
connected_track_list_(nullptr),
|
||||
show_thumbnails_(true),
|
||||
show_waveforms_(true),
|
||||
transition_overlay_out_(nullptr),
|
||||
transition_overlay_in_(nullptr)
|
||||
@@ -519,12 +520,32 @@ void TimelineView::DrawBlock(QPainter *painter, bool foreground, Block *block, q
|
||||
painter->drawRect(r);
|
||||
|
||||
if (ClipBlock *clip = dynamic_cast<ClipBlock*>(block)) {
|
||||
QRect preview_rect = r.adjusted(0, text_total_height, 0, 0).toRect();
|
||||
|
||||
// Draw clip thumbnails
|
||||
if (clip->GetTrackType() == Track::kVideo && show_thumbnails_ && preview_rect.height() > r.height()/3) {
|
||||
const int kTempThumbWidth = 120;
|
||||
const int kTempThumbHeight = 68;
|
||||
|
||||
QRect thumb_rect;
|
||||
painter->setClipRect(preview_rect);
|
||||
for (int i=preview_rect.left(); i<preview_rect.right(); i+=thumb_rect.width()+1) {
|
||||
double scale = double(preview_rect.height())/double(kTempThumbHeight);
|
||||
thumb_rect = QRect(i, preview_rect.top(), kTempThumbWidth * scale, preview_rect.height());
|
||||
|
||||
painter->fillRect(thumb_rect, Qt::red);
|
||||
}
|
||||
painter->setClipping(false);
|
||||
}
|
||||
|
||||
// Draw waveform
|
||||
if (show_waveforms_) {
|
||||
QRect waveform_rect = r.adjusted(0, text_total_height, 0, 0).toRect();
|
||||
painter->setPen(shadow_color);
|
||||
AudioVisualWaveform::DrawWaveform(painter, waveform_rect, this->GetScale(), clip->waveform(),
|
||||
SceneToTime(block_left - block_in, GetScale(), connected_track_list_->parent()->GetAudioParams().sample_rate_as_time_base()) + media_in);
|
||||
if (clip->GetTrackType() == Track::kAudio && show_waveforms_) {
|
||||
if (const AudioVisualWaveform *wave = clip->waveform()) {
|
||||
rational waveform_start = SceneToTime(block_left - block_in, GetScale(), connected_track_list_->parent()->GetAudioParams().sample_rate_as_time_base()) + media_in;
|
||||
painter->setPen(shadow_color);
|
||||
|
||||
AudioVisualWaveform::DrawWaveform(painter, preview_rect, this->GetScale(), *wave, waveform_start);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw zebra stripes and markers
|
||||
|
||||
@@ -153,6 +153,7 @@ private:
|
||||
|
||||
TrackList* connected_track_list_;
|
||||
|
||||
bool show_thumbnails_;
|
||||
bool show_waveforms_;
|
||||
|
||||
ClipBlock *transition_overlay_out_;
|
||||
|
||||
@@ -147,6 +147,8 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
|
||||
setAcceptDrops(true);
|
||||
|
||||
auto_cacher_ = new PreviewAutoCacher(this);
|
||||
|
||||
connect(Core::instance(), &Core::ColorPickerEnabled, this, &ViewerWidget::SetSignalCursorColorEnabled);
|
||||
connect(this, &ViewerWidget::CursorColor, Core::instance(), &Core::ColorPickerColorEmitted);
|
||||
connect(AudioManager::instance(), &AudioManager::OutputParamsChanged, this, &ViewerWidget::UpdateAudioProcessor);
|
||||
@@ -191,7 +193,7 @@ void ViewerWidget::TimeChangedEvent(const rational &time)
|
||||
}
|
||||
|
||||
// Send time to auto-cacher
|
||||
auto_cacher_.SetPlayhead(time);
|
||||
auto_cacher_->SetPlayhead(time);
|
||||
|
||||
last_time_ = time;
|
||||
}
|
||||
@@ -275,7 +277,7 @@ void ViewerWidget::DisconnectNodeEvent(ViewerOutput *n)
|
||||
|
||||
void ViewerWidget::ConnectedNodeChangeEvent(ViewerOutput *n)
|
||||
{
|
||||
auto_cacher_.SetViewerNode(n);
|
||||
auto_cacher_->SetViewerNode(n);
|
||||
display_widget_->SetSubtitleTracks(dynamic_cast<Sequence*>(n));
|
||||
}
|
||||
|
||||
@@ -369,13 +371,13 @@ void ViewerWidget::SetFullScreen(QScreen *screen)
|
||||
|
||||
void ViewerWidget::CacheEntireSequence()
|
||||
{
|
||||
auto_cacher_.ForceCacheRange(TimeRange(0, GetConnectedNode()->GetVideoLength()));
|
||||
auto_cacher_->ForceCacheRange(TimeRange(0, GetConnectedNode()->GetVideoLength()));
|
||||
}
|
||||
|
||||
void ViewerWidget::CacheSequenceInOut()
|
||||
{
|
||||
if (GetConnectedNode() && GetConnectedNode()->GetTimelinePoints()->workarea()->enabled()) {
|
||||
auto_cacher_.ForceCacheRange(GetConnectedNode()->GetTimelinePoints()->workarea()->range());
|
||||
auto_cacher_->ForceCacheRange(GetConnectedNode()->GetTimelinePoints()->workarea()->range());
|
||||
} else {
|
||||
QMessageBox::warning(this,
|
||||
tr("Error"),
|
||||
@@ -442,12 +444,12 @@ void ViewerWidget::SetEmptyImage()
|
||||
|
||||
void ViewerWidget::UpdateAutoCacher()
|
||||
{
|
||||
auto_cacher_.SetPlayhead(GetTime());
|
||||
auto_cacher_->SetPlayhead(GetTime());
|
||||
}
|
||||
|
||||
void ViewerWidget::ClearVideoAutoCacherQueue()
|
||||
{
|
||||
auto_cacher_.CancelVideoTasks();
|
||||
auto_cacher_->CancelVideoTasks();
|
||||
}
|
||||
|
||||
void ViewerWidget::DecrementPrequeuedAudio()
|
||||
@@ -549,7 +551,7 @@ void ViewerWidget::QueueNextAudioBuffer()
|
||||
RenderTicketWatcher *watcher = new RenderTicketWatcher(this);
|
||||
connect(watcher, &RenderTicketWatcher::Finished, this, &ViewerWidget::ReceivedAudioBufferForPlayback);
|
||||
audio_playback_queue_.push_back(watcher);
|
||||
watcher->SetTicket(auto_cacher_.GetRangeOfAudio(TimeRange(audio_playback_queue_time_, queue_end), RenderTicketPriority::kHigh));
|
||||
watcher->SetTicket(auto_cacher_->GetRangeOfAudio(TimeRange(audio_playback_queue_time_, queue_end), RenderTicketPriority::kHigh));
|
||||
|
||||
audio_playback_queue_time_ = queue_end;
|
||||
}
|
||||
@@ -685,7 +687,7 @@ void ViewerWidget::UpdateTextureFromNode()
|
||||
nonqueue_watchers_.append(watcher);
|
||||
|
||||
// Clear queue because we want this frame more than any others
|
||||
if (!GetConnectedNode()->video_frame_cache()->IsEnabled() && !auto_cacher_.IsRenderingCustomRange()) {
|
||||
if (!GetConnectedNode()->video_frame_cache()->IsAutomatic() && !auto_cacher_->IsRenderingCustomRange()) {
|
||||
ClearVideoAutoCacherQueue();
|
||||
}
|
||||
|
||||
@@ -716,10 +718,8 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
|
||||
foreach (ViewerWidget* viewer, instances_) {
|
||||
if (viewer != this) {
|
||||
viewer->PauseInternal();
|
||||
viewer->ClearVideoAutoCacherQueue();
|
||||
viewer->auto_cacher_->SetRendersPaused(true);
|
||||
}
|
||||
|
||||
viewer->auto_cacher_.SetAudioPaused(true);
|
||||
}
|
||||
|
||||
// Disarm recording if armed
|
||||
@@ -823,7 +823,7 @@ void ViewerWidget::PauseInternal()
|
||||
UpdateAudioProcessor();
|
||||
|
||||
foreach (ViewerWidget* viewer, instances_) {
|
||||
viewer->auto_cacher_.SetAudioPaused(false);
|
||||
viewer->auto_cacher_->SetRendersPaused(false);
|
||||
}
|
||||
|
||||
UpdateTextureFromNode();
|
||||
@@ -848,7 +848,7 @@ void ViewerWidget::PushScrubbedAudio()
|
||||
|
||||
RenderTicketWatcher *watcher = new RenderTicketWatcher();
|
||||
connect(watcher, &RenderTicketWatcher::Finished, this, &ViewerWidget::ReceivedAudioBufferForScrubbing);
|
||||
watcher->SetTicket(auto_cacher_.GetRangeOfAudio(TimeRange(GetTime(), GetTime() + interval), RenderTicketPriority::kHigh));
|
||||
watcher->SetTicket(auto_cacher_->GetRangeOfAudio(TimeRange(GetTime(), GetTime() + interval), RenderTicketPriority::kHigh));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -922,7 +922,7 @@ RenderTicketPtr ViewerWidget::GetFrame(const rational &t, RenderTicketPriority p
|
||||
|
||||
if (!QFileInfo::exists(cache_fn)) {
|
||||
// Frame hasn't been cached, start render job
|
||||
return auto_cacher_.GetSingleFrame(t, priority);
|
||||
return auto_cacher_->GetSingleFrame(t, priority);
|
||||
} else {
|
||||
// Frame has been cached, grab the frame
|
||||
RenderTicketPtr ticket = std::make_shared<RenderTicket>();
|
||||
|
||||
@@ -255,7 +255,7 @@ private:
|
||||
int prequeue_length_;
|
||||
int prequeue_count_;
|
||||
|
||||
PreviewAutoCacher auto_cacher_;
|
||||
PreviewAutoCacher *auto_cacher_;
|
||||
|
||||
QVector<RenderTicketWatcher*> queue_watchers_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user