From 7e6d4dce20751168e6b9c1be1874de0e4b7467de Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 11 Aug 2018 20:06:20 +1000 Subject: [PATCH] nicer effects panel, improved split selection --- dialogs/exportdialog.ui | 40 ++++----- effects/crossdissolvetransition.cpp | 17 ---- effects/effects.cpp | 2 + effects/effects.h | 14 +++ effects/inverteffect.cpp | 51 +++++++++++ effects/linearfadetransition.cpp | 26 ++++++ effects/transition.h | 24 +++-- mainwindow.cpp | 2 +- olive.pro | 4 +- panels/effectcontrols.cpp | 62 ++++++++++--- panels/effectcontrols.h | 11 +-- panels/effectcontrols.ui | 4 +- panels/timeline.cpp | 23 ++++- panels/timeline.h | 2 +- panels/timeline.ui | 18 ++-- playback/audio.cpp | 4 +- project/clip.cpp | 1 + ui/timelinewidget.cpp | 2 +- ui/viewerwidget.cpp | 132 ++++++++++++++-------------- ui/viewerwidget.h | 18 ++-- 20 files changed, 302 insertions(+), 155 deletions(-) create mode 100644 effects/inverteffect.cpp create mode 100644 effects/linearfadetransition.cpp diff --git a/dialogs/exportdialog.ui b/dialogs/exportdialog.ui index df0d18d2f..9e1a43f4d 100644 --- a/dialogs/exportdialog.ui +++ b/dialogs/exportdialog.ui @@ -6,8 +6,8 @@ 0 0 - 557 - 659 + 358 + 442 @@ -75,13 +75,6 @@ - - - - Width: - - - @@ -89,6 +82,13 @@ + + + + Width: + + + @@ -120,14 +120,14 @@ - + Bitrate (Mbps/CBR): - + 100.000000000000000 @@ -159,13 +159,6 @@ - - - - Sampling Rate: - - - @@ -176,14 +169,21 @@ - + + + + Sampling Rate: + + + + Bitrate (Kbps/CBR): - + 320 diff --git a/effects/crossdissolvetransition.cpp b/effects/crossdissolvetransition.cpp index 16b0c2640..b112615fe 100644 --- a/effects/crossdissolvetransition.cpp +++ b/effects/crossdissolvetransition.cpp @@ -10,23 +10,6 @@ void CrossDissolveTransition::process_transition(double progress) { glColor4f(1.0, 1.0, 1.0, color[3]*progress); } -void CrossDissolveTransition::process_audio(double range_start, double range_end, quint8* samples, int nb_samples, bool reverse) { - double interval = (range_end - range_start) / nb_samples; - - for (int i=0;i> 8); - samples[i] = (quint8) samp; - } -} - Transition* CrossDissolveTransition::copy() { Transition* t = new CrossDissolveTransition(); t->length = length; diff --git a/effects/effects.cpp b/effects/effects.cpp index b4f216bc7..af785ab8c 100644 --- a/effects/effects.cpp +++ b/effects/effects.cpp @@ -16,6 +16,7 @@ void init_effects() { video_effect_names[VIDEO_SHAKE_EFFECT] = "Shake"; video_effect_names[VIDEO_TEXT_EFFECT] = "Text"; video_effect_names[VIDEO_SOLID_EFFECT] = "Solid"; + video_effect_names[VIDEO_INVERT_EFFECT] = "Invert"; audio_effect_names[AUDIO_VOLUME_EFFECT] = "Volume"; audio_effect_names[AUDIO_PAN_EFFECT] = "Pan"; @@ -28,6 +29,7 @@ Effect* create_effect(int effect_id, Clip* c) { case VIDEO_SHAKE_EFFECT: return new ShakeEffect(c); break; case VIDEO_TEXT_EFFECT: return new TextEffect(c); break; case VIDEO_SOLID_EFFECT: return new SolidEffect(c); break; + case VIDEO_INVERT_EFFECT: return new InvertEffect(c); break; } } else { switch (effect_id) { diff --git a/effects/effects.h b/effects/effects.h index 5a887bdad..cbbdf5613 100644 --- a/effects/effects.h +++ b/effects/effects.h @@ -21,6 +21,7 @@ enum VideoEffects { VIDEO_SHAKE_EFFECT, VIDEO_TEXT_EFFECT, VIDEO_SOLID_EFFECT, + VIDEO_INVERT_EFFECT, VIDEO_EFFECT_COUNT }; @@ -130,6 +131,19 @@ private: QOpenGLTexture* texture; }; +class InvertEffect : public Effect { + Q_OBJECT +public: + InvertEffect(Clip* c); + void init(); + void process_gl(int *anchor_x, int *anchor_y); + Effect* copy(Clip *c); + void load(QXmlStreamReader* stream); + void save(QXmlStreamWriter* stream); + + LabelSlider* amount_val; +}; + // audio effects class VolumeEffect : public Effect { public: diff --git a/effects/inverteffect.cpp b/effects/inverteffect.cpp new file mode 100644 index 000000000..4f399f44f --- /dev/null +++ b/effects/inverteffect.cpp @@ -0,0 +1,51 @@ +#include "effects/effects.h" + +#include "ui/labelslider.h" + +#include +#include +#include +#include +#include + +InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_EFFECT) { + ui_layout->addWidget(new QLabel("Amount:"), 0, 0); + amount_val = new LabelSlider(); + ui_layout->addWidget(amount_val, 0, 1); + + // set defaults + amount_val->set_minimum_value(0); + amount_val->set_maximum_value(100); + init(); + + connect(amount_val, SIGNAL(valueChanged()), this, SLOT(field_changed())); +} + +void InvertEffect::init() { + amount_val->set_default_value(100); +} + +Effect* InvertEffect::copy(Clip* c) { + InvertEffect* i = new InvertEffect(c); + i->amount_val->set_value(amount_val->value()); + return i; +} + +void InvertEffect::load(QXmlStreamReader *stream) { + const QXmlStreamAttributes& attr = stream->attributes(); + for (int i=0;iset_value(a.value().toDouble()); + } + } +} + +void InvertEffect::save(QXmlStreamWriter *stream) { + stream->writeAttribute("amount", QString::number(amount_val->value())); +} + +void InvertEffect::process_gl(int* anchor_x, int* anchor_y) { + +// gl_FragColor = vec4(1.0 - textureColor.r, 1.0 -textureColor.g, 1.0 -textureColor.b, 1); +} diff --git a/effects/linearfadetransition.cpp b/effects/linearfadetransition.cpp new file mode 100644 index 000000000..6cf1edf7e --- /dev/null +++ b/effects/linearfadetransition.cpp @@ -0,0 +1,26 @@ +#include "transition.h" + +LinearFadeTransition::LinearFadeTransition() : Transition(AUDIO_LINEAR_FADE_TRANSITION) {} + +void LinearFadeTransition::process_audio(double range_start, double range_end, quint8* samples, int nb_samples, bool reverse) { + double interval = (range_end - range_start) / nb_samples; + + for (int i=0;i> 8); + samples[i] = (quint8) samp; + } +} + +Transition* LinearFadeTransition::copy() { + Transition* t = new LinearFadeTransition(); + t->length = length; + return t; +} diff --git a/effects/transition.h b/effects/transition.h index b163cea7e..3f9f7ec80 100644 --- a/effects/transition.h +++ b/effects/transition.h @@ -15,11 +15,6 @@ enum AudioTransitions { AUDIO_TRANSITION_COUNT }; -void init_transitions(); - -extern QVector video_transition_names; -extern QVector audio_transition_names; - class Transition { public: @@ -28,20 +23,31 @@ public: int id; QString name; int length; - Transition* link; + Transition* link; virtual void process_transition(double); virtual void process_audio(double, double, quint8*, int, bool); - virtual Transition* copy(); + virtual Transition* copy(); }; +void init_transitions(); +Transition* create_transition(int transition_id, Clip* c); +extern QVector video_transition_names; +extern QVector audio_transition_names; + +// Video Transitions class CrossDissolveTransition : public Transition { public: CrossDissolveTransition(); void process_transition(double); - void process_audio(double, double, quint8*, int, bool); Transition* copy(); }; -Transition* create_transition(int transition_id, Clip* c); +// Audio Transitions +class LinearFadeTransition : public Transition { +public: + LinearFadeTransition(); + void process_audio(double, double, quint8*, int, bool); + Transition* copy(); +}; #endif // TRANSITION_H diff --git a/mainwindow.cpp b/mainwindow.cpp index ee2c011e6..b3523e48a 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -79,7 +79,7 @@ MainWindow::MainWindow(QWidget *parent) : ui->setupUi(this); - setWindowTitle("Olive (August 2018 | Pre-Alpha)"); + setWindowTitle("Olive (August 2018 | Alpha)"); statusBar()->showMessage("Welcome to Olive"); ui->centralWidget->setMaximumSize(0, 0); diff --git a/olive.pro b/olive.pro index 258974f53..9dbd02ddf 100644 --- a/olive.pro +++ b/olive.pro @@ -66,7 +66,9 @@ SOURCES += \ ui/comboboxex.cpp \ ui/colorbutton.cpp \ effects/solideffect.cpp \ - dialogs/replaceclipmediadialog.cpp + dialogs/replaceclipmediadialog.cpp \ + effects/inverteffect.cpp \ + effects/linearfadetransition.cpp HEADERS += \ mainwindow.h \ diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index 98ad273f7..f6f316f15 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -14,6 +14,7 @@ #include "project/sequence.h" #include "project/undo.h" #include "panels/project.h" +#include "panels/timeline.h" EffectControls::EffectControls(QWidget *parent) : QDockWidget(parent), @@ -33,26 +34,51 @@ EffectControls::~EffectControls() void EffectControls::menu_select(QAction* q) { TimelineAction* ta = new TimelineAction(); for (int i=0;iget_clip(selected_clips.at(i))->track < 0) == video_menu) { - ta->add_effect(sequence, selected_clips.at(i), q->data().toInt()); + Clip* c = sequence->get_clip(selected_clips.at(i)); + if (c->track < 0 == video_menu) { + if (transition_menu) { + if (c->opening_transition == NULL) { + ta->add_transition(sequence, selected_clips.at(i), q->data().toInt(), TA_OPENING_TRANSITION); + } + if (c->closing_transition == NULL) { + ta->add_transition(sequence, selected_clips.at(i), q->data().toInt(), TA_CLOSING_TRANSITION); + } + } else { + ta->add_effect(sequence, selected_clips.at(i), q->data().toInt()); + } } } undo_stack.push(ta); - reload_clips(); + if (transition_menu) { + panel_timeline->redraw_all_clips(true); + } else { + reload_clips(); + } } -void EffectControls::show_menu(bool video) { +void EffectControls::show_effect_menu(bool video, bool transitions) { video_menu = video; + transition_menu = transitions; int lim; QVector* effect_names; - if (video) { - lim = VIDEO_EFFECT_COUNT; - effect_names = &video_effect_names; - } else { - lim = AUDIO_EFFECT_COUNT; - effect_names = &audio_effect_names; - } + if (transitions) { + if (video) { + lim = VIDEO_TRANSITION_COUNT; + effect_names = &video_transition_names; + } else { + lim = AUDIO_TRANSITION_COUNT; + effect_names = &audio_transition_names; + } + } else { + if (video) { + lim = VIDEO_EFFECT_COUNT; + effect_names = &video_effect_names; + } else { + lim = AUDIO_EFFECT_COUNT; + effect_names = &audio_effect_names; + } + } QMenu effects_menu(this); @@ -168,12 +194,22 @@ void EffectControls::set_clips(QVector& clips) { void EffectControls::on_add_video_effect_button_clicked() { - show_menu(true); + show_effect_menu(true, false); } void EffectControls::on_add_audio_effect_button_clicked() { - show_menu(false); + show_effect_menu(false, false); +} + +void EffectControls::on_add_video_transition_button_clicked() +{ + show_effect_menu(true, true); +} + +void EffectControls::on_add_audio_transition_button_clicked() +{ + show_effect_menu(false, true); } bool EffectControls::is_focused() { diff --git a/panels/effectcontrols.h b/panels/effectcontrols.h index be4ac8a7b..50cab070e 100644 --- a/panels/effectcontrols.h +++ b/panels/effectcontrols.h @@ -19,7 +19,6 @@ class EffectControls : public QDockWidget public: explicit EffectControls(QWidget *parent = 0); ~EffectControls(); - // void set_clip(Clip* c); void set_clips(QVector& clips); void clear_effects(bool clear_cache); void delete_effects(); @@ -28,20 +27,22 @@ public: private slots: void menu_select(QAction* q); - void on_add_video_effect_button_clicked(); - void on_add_audio_effect_button_clicked(); + void deselect_all_effects(QWidget*); - void deselect_all_effects(QWidget*); + void on_add_video_transition_button_clicked(); + + void on_add_audio_transition_button_clicked(); private: Ui::EffectControls *ui; QVector selected_clips; - void show_menu(bool video); + void show_effect_menu(bool video, bool transitions); void load_effects(); bool video_menu; + bool transition_menu; }; /*class EffectAddCommand : public QUndoCommand { diff --git a/panels/effectcontrols.ui b/panels/effectcontrols.ui index c1b26eec2..a5c46f64e 100644 --- a/panels/effectcontrols.ui +++ b/panels/effectcontrols.ui @@ -173,7 +173,7 @@ - + Add Video Transition @@ -318,7 +318,7 @@ - + Add Audio Transition diff --git a/panels/timeline.cpp b/panels/timeline.cpp index ea49e9631..9aed6d8af 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -50,7 +50,7 @@ Timeline::Timeline(QWidget *parent) : ui(new Ui::Timeline), last_frame(0) { - default_track_height = (QGuiApplication::primaryScreen()->logicalDotsPerInch() / 96) * default_track_height; + default_track_height = (QGuiApplication::primaryScreen()->logicalDotsPerInch() / 96) * TRACK_DEFAULT_HEIGHT; ui->setupUi(this); @@ -215,7 +215,7 @@ int Timeline::calculate_track_height(int track, int value) { int index = (track < 0) ? qAbs(track + 1) : track; QVector& vector = (track < 0) ? video_track_heights : audio_track_heights; while (vector.size() < index+1) { - vector.append(TRACK_DEFAULT_HEIGHT); + vector.append(default_track_height); } if (value > -1) { vector[index] = value; @@ -837,19 +837,34 @@ bool Timeline::split_selection(TimelineAction* ta) { for (int i=0;itrack) { - if (clip->timeline_in < s.in && clip->timeline_out > s.out) { + if (clip->timeline_in < s.in && clip->timeline_out > s.out) { Clip* split_A = clip->copy(sequence); split_A->clip_in += (s.in - clip->timeline_in); split_A->timeline_in = s.in; split_A->timeline_out = s.out; pre_splits.append(j); - post_splits.append(split_A); + post_splits.append(split_A); Clip* split_B = clip->copy(sequence); split_B->clip_in += (s.out - clip->timeline_in); split_B->timeline_in = s.out; secondary_post_splits.append(split_B); + if (clip->opening_transition != NULL) { + delete split_B->opening_transition; + split_B->opening_transition = NULL; + + delete split_A->opening_transition; + split_A->opening_transition = NULL; + } + + if (clip->closing_transition != NULL) { + ta->delete_transition(sequence, j, TA_CLOSING_TRANSITION); + + delete split_A->closing_transition; + split_A->closing_transition = NULL; + } + ta->set_timeline_out(sequence, j, s.in); split = true; } else { diff --git a/panels/timeline.h b/panels/timeline.h index 33b47b461..f5e57729f 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -2,6 +2,7 @@ #define TIMELINE_H #include "ui/timelinetools.h" + #include #include #include @@ -68,7 +69,6 @@ class Timeline; class Timeline : public QDockWidget { Q_OBJECT - public: explicit Timeline(QWidget *parent = 0); ~Timeline(); diff --git a/panels/timeline.ui b/panels/timeline.ui index 9df286d0c..126e6b0b7 100644 --- a/panels/timeline.ui +++ b/panels/timeline.ui @@ -33,7 +33,7 @@ - + 0 0 @@ -272,7 +272,7 @@ 0 0 819 - 551 + 557 @@ -309,6 +309,12 @@ Qt::Vertical + + false + + + false + QFrame::NoFrame @@ -327,8 +333,8 @@ 0 0 - 802 - 266 + 805 + 269 @@ -378,8 +384,8 @@ 0 0 - 802 - 265 + 805 + 269 diff --git a/playback/audio.cpp b/playback/audio.cpp index c51a6f7c7..7b7b64fc5 100644 --- a/playback/audio.cpp +++ b/playback/audio.cpp @@ -38,8 +38,8 @@ void init_audio() { if (!info.isFormatSupported(audio_format)) { qWarning() << "[WARNING] Couldn't initialize audio. Audio format is not supported by backend"; } else { - audio_output = new QAudioOutput(audio_format); - audio_output->setBufferSize(20480); + audio_output = new QAudioOutput(audio_format); + audio_output->setBufferSize(20480); // connect audio_io_device = audio_output->start(); diff --git a/project/clip.cpp b/project/clip.cpp index facf772c8..d454e37b5 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -131,6 +131,7 @@ void Clip::run_video_pre_effect_stack(long playhead, int* anchor_x, int* anchor_ opening_transition->process_transition((double)transition_progress/(double)opening_transition->length); } } + if (closing_transition != NULL) { int transition_progress = closing_transition->length - (playhead - timeline_in - getLength() + closing_transition->length); if (transition_progress < closing_transition->length) { diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 2cfa5af90..d8c75e9b9 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -1579,7 +1579,7 @@ void TimelineWidget::redraw_clips() { } } - if (minimumWidth() != panel_width || /*clip_pixmap.height() != height() || */panel_height != minimumHeight()) { + if (minimumWidth() != panel_width || clip_pixmap.height() != height() || panel_height != minimumHeight()) { setMinimumWidth(panel_width); container->setMinimumWidth(panel_width); setMinimumHeight(panel_height); diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index c4a6eb0af..47e44fd5b 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -32,7 +32,7 @@ ViewerWidget::ViewerWidget(QWidget *parent) : setFormat(format); // start audio sending thread - audio_sender_thread.start(); + audio_sender_thread.start(); // error handler - retries after 250ms if we couldn't get the entire image retry_timer.setInterval(250); @@ -40,9 +40,9 @@ ViewerWidget::ViewerWidget(QWidget *parent) : } ViewerWidget::~ViewerWidget() { - audio_sender_thread.close = true; + audio_sender_thread.close = true; audio_sender_thread.cond.wakeAll(); - audio_sender_thread.wait(); + audio_sender_thread.wait(); } void ViewerWidget::deleteFunction() { @@ -87,12 +87,14 @@ void ViewerWidget::paintEvent(QPaintEvent *e) { if (enable_paint) QOpenGLWidget::paintEvent(e); } -void ViewerWidget::compose_sequence(Clip* nest, bool render_audio) { +void ViewerWidget::compose_sequence(QVector& nests, bool render_audio) { Sequence* s = sequence; long playhead = panel_timeline->playhead; - if (nest != NULL) { - s = static_cast(nest->media); + Clip* nest = NULL; + if (nests.size() > 0) { + nest = nests.last(); + s = static_cast(nest->media); playhead += nest->clip_in - nest->timeline_in; playhead = refactor_frame_number(playhead, sequence->frame_rate, s->frame_rate); } @@ -157,8 +159,7 @@ void ViewerWidget::compose_sequence(Clip* nest, bool render_audio) { texture_failed = true; } else { switch (c->media_type) { - case MEDIA_TYPE_FOOTAGE: - qDebug() << "clip"; + case MEDIA_TYPE_FOOTAGE: if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { // start preparing cache get_clip_frame(c, playhead); @@ -183,9 +184,9 @@ void ViewerWidget::compose_sequence(Clip* nest, bool render_audio) { // perform all transform effects c->run_video_pre_effect_stack(playhead, &anchor_x, &anchor_y); - if (nest != NULL) { - nest->run_video_pre_effect_stack(playhead, &anchor_x, &anchor_y); - } + for (int i=nests.size()-1;i>=0;i--) { + nests.at(i)->run_video_pre_effect_stack(playhead, &anchor_x, &anchor_y); + } int anchor_right = ms->video_width - anchor_x; int anchor_bottom = ms->video_height - anchor_y; @@ -217,8 +218,8 @@ void ViewerWidget::compose_sequence(Clip* nest, bool render_audio) { } break; case MEDIA_TYPE_SEQUENCE: - qDebug() << "nest"; - compose_sequence(c, render_audio); + nests.append(c); + compose_sequence(nests, render_audio); c->run_video_post_effect_stack(); break; } @@ -237,12 +238,13 @@ void ViewerWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT); // compose video preview - compose_sequence(NULL, (panel_timeline->playing || force_audio)); + QVector nests; + compose_sequence(nests, (panel_timeline->playing || force_audio)); - // send audio to IO device - if (panel_timeline->playing) { - audio_sender_thread.cond.wakeAll(); - } + // send audio to IO device + if (panel_timeline->playing) { + audio_sender_thread.cond.wakeAll(); + } if (texture_failed) { if (multithreaded) { @@ -256,60 +258,62 @@ void ViewerWidget::paintGL() { } AudioSenderThread::AudioSenderThread() : close(false) { - connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); + connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); } void AudioSenderThread::run() { - lock.lock(); - while (true) { - cond.wait(&lock); - if (close) { - break; - } else { - int written_bytes = 0; + lock.lock(); + while (true) { + cond.wait(&lock); + if (close) { + break; + } else { + int written_bytes = 0; - int adjusted_read_index = audio_ibuffer_read%audio_ibuffer_size; - int max_write = audio_ibuffer_size - adjusted_read_index; - int actual_write = send_audio_to_output(adjusted_read_index, max_write); - written_bytes += actual_write; - if (actual_write == max_write) { - // got all the bytes, write again - written_bytes += send_audio_to_output(0, audio_ibuffer_size); - } - } - } - lock.unlock(); + int adjusted_read_index = audio_ibuffer_read%audio_ibuffer_size; + int max_write = audio_ibuffer_size - adjusted_read_index; + int actual_write = send_audio_to_output(adjusted_read_index, max_write); + written_bytes += actual_write; + if (actual_write == max_write) { + // got all the bytes, write again + written_bytes += send_audio_to_output(0, audio_ibuffer_size); + } + + qDebug() << "WB:" << written_bytes; + } + } + lock.unlock(); } int AudioSenderThread::send_audio_to_output(int offset, int max) { - // send audio to device - int actual_write = audio_io_device->write((const char*) audio_ibuffer+offset, max); - audio_ibuffer_read += actual_write; + // send audio to device + int actual_write = audio_io_device->write((const char*) audio_ibuffer+offset, max); + audio_ibuffer_read += actual_write; - // send samples to audio monitor cache - if (panel_timeline->ui->audio_monitor->sample_cache_offset == -1) { - panel_timeline->ui->audio_monitor->sample_cache_offset = panel_timeline->playhead; - } - long sample_cache_playhead = panel_timeline->ui->audio_monitor->sample_cache_offset + panel_timeline->ui->audio_monitor->sample_cache.size(); - int next_buffer_offset, buffer_offset_adjusted, i; - int buffer_offset = get_buffer_offset_from_frame(sample_cache_playhead); - samples.resize(av_get_channel_layout_nb_channels(sequence->audio_layout)); - samples.fill(0); - while (buffer_offset < audio_ibuffer_read) { - sample_cache_playhead++; - next_buffer_offset = qMin(get_buffer_offset_from_frame(sample_cache_playhead), audio_ibuffer_read); - while (buffer_offset < next_buffer_offset) { - for (i=0;iui->audio_monitor->sample_cache.append(samples); - buffer_offset = next_buffer_offset; - } + // send samples to audio monitor cache + if (panel_timeline->ui->audio_monitor->sample_cache_offset == -1) { + panel_timeline->ui->audio_monitor->sample_cache_offset = panel_timeline->playhead; + } + long sample_cache_playhead = panel_timeline->ui->audio_monitor->sample_cache_offset + panel_timeline->ui->audio_monitor->sample_cache.size(); + int next_buffer_offset, buffer_offset_adjusted, i; + int buffer_offset = get_buffer_offset_from_frame(sample_cache_playhead); + samples.resize(av_get_channel_layout_nb_channels(sequence->audio_layout)); + samples.fill(0); + while (buffer_offset < audio_ibuffer_read) { + sample_cache_playhead++; + next_buffer_offset = qMin(get_buffer_offset_from_frame(sample_cache_playhead), audio_ibuffer_read); + while (buffer_offset < next_buffer_offset) { + for (i=0;iui->audio_monitor->sample_cache.append(samples); + buffer_offset = next_buffer_offset; + } - memset(audio_ibuffer+offset, 0, actual_write); + memset(audio_ibuffer+offset, 0, actual_write); - return actual_write; + return actual_write; } diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index 7e2ba1da6..e04b0944a 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -15,14 +15,14 @@ struct Sequence; class AudioSenderThread : public QThread { public: - AudioSenderThread(); - void run(); - QWaitCondition cond; - bool close; - QMutex lock; + AudioSenderThread(); + void run(); + QWaitCondition cond; + bool close; + QMutex lock; private: - QVector samples; - int send_audio_to_output(int offset, int max); + QVector samples; + int send_audio_to_output(int offset, int max); }; class ViewerWidget : public QOpenGLWidget, public QOpenGLFunctions @@ -43,11 +43,11 @@ protected: // void resizeGL(int w, int h); private: QTimer retry_timer; - AudioSenderThread audio_sender_thread; + AudioSenderThread audio_sender_thread; private slots: void retry(); void deleteFunction(); - void compose_sequence(Clip *nest, bool render_audio); + void compose_sequence(QVector& nests, bool render_audio); }; #endif // VIEWERWIDGET_H