diff --git a/dialogs/exportdialog.ui b/dialogs/exportdialog.ui
index ce1b53b70..3434cb213 100644
--- a/dialogs/exportdialog.ui
+++ b/dialogs/exportdialog.ui
@@ -247,6 +247,22 @@
+
+ formatCombobox
+ videoGroupbox
+ vcodecCombobox
+ widthSpinbox
+ heightSpinbox
+ framerateSpinbox
+ videobitrateSpinbox
+ audioGroupbox
+ acodecCombobox
+ samplingRateSpinbox
+ audiobitrateSpinbox
+ renderCancel
+ pushButton
+ pushButton_2
+
diff --git a/dialogs/newsequencedialog.ui b/dialogs/newsequencedialog.ui
index de589f8ee..3a9663340 100644
--- a/dialogs/newsequencedialog.ui
+++ b/dialogs/newsequencedialog.ui
@@ -322,6 +322,16 @@
+
+ comboBox
+ width_numeric
+ height_numeric
+ frame_rate_combobox
+ par_combobox
+ interlacing_combobox
+ audio_frequency_combobox
+ lineEdit
+
diff --git a/effects/volumeeffect.cpp b/effects/volumeeffect.cpp
index 0650d55a1..986a8c23c 100644
--- a/effects/volumeeffect.cpp
+++ b/effects/volumeeffect.cpp
@@ -17,7 +17,7 @@ VolumeEffect::VolumeEffect(Clip* c) : Effect(c) {
ui_layout->addWidget(new QLabel("Volume:"), 0, 0);
volume_val = new QSpinBox();
volume_val->setMinimum(0);
- volume_val->setMaximum(100);
+ volume_val->setMaximum(400);
ui_layout->addWidget(volume_val, 0, 1);
ui->setLayout(ui_layout);
diff --git a/io/config.cpp b/io/config.cpp
index d751e595e..c655a45e4 100644
--- a/io/config.cpp
+++ b/io/config.cpp
@@ -29,7 +29,7 @@ void load_config() {
#endif
}*/
- padding *= scale;
+// padding *= scale;
/*DIR* dir = opendir("conf");
if (dir) {
diff --git a/io/config.h b/io/config.h
index 1bd410f1b..7a618c2ce 100644
--- a/io/config.h
+++ b/io/config.h
@@ -5,7 +5,7 @@ extern const char* version;
extern float scale;
extern bool vsync;
extern bool hwaccel;
-extern int padding;
+//extern int padding;
extern bool custom_scale;
extern bool saved_layout;
extern bool show_track_lines;
diff --git a/io/exportthread.cpp b/io/exportthread.cpp
index 91ac166d5..9a67eea81 100644
--- a/io/exportthread.cpp
+++ b/io/exportthread.cpp
@@ -110,11 +110,11 @@ void ExportThread::run() {
qDebug() << "[ERROR] Could not find allocate video encoding context";
fail = true;
} else {
- vcodec_ctx->width = sequence->width;
- vcodec_ctx->height = sequence->height;
- vcodec_ctx->sample_aspect_ratio = av_d2q(sequence->width/sequence->height, INT_MAX);
+ vcodec_ctx->width = video_width;
+ vcodec_ctx->height = video_height;
+ vcodec_ctx->sample_aspect_ratio = av_d2q(video_width/video_height, INT_MAX);
vcodec_ctx->pix_fmt = vcodec->pix_fmts[0]; // maybe be breakable code
- vcodec_ctx->framerate = av_d2q(sequence->frame_rate, INT_MAX);
+ vcodec_ctx->framerate = av_d2q(video_frame_rate, INT_MAX);
vcodec_ctx->bit_rate = video_bitrate * 1000000;
vcodec_ctx->time_base = av_inv_q(vcodec_ctx->framerate);
@@ -266,15 +266,7 @@ void ExportThread::run() {
if (ret < 0) {
qDebug() << "[ERROR] Could not write output file header." << ret;
} else {
- panel_timeline->seek(0);
-
- // clean up - close all open clips
- for (int i=0;iclip_count();i++) {
- Clip& c = sequence->get_clip(i);
- if (c.open) {
- close_clip(&c);
- }
- }
+ panel_timeline->seek(start);
QOpenGLFramebufferObject fbo(video_width, video_height, QOpenGLFramebufferObject::CombinedDepthStencil, GL_TEXTURE_RECTANGLE);
fbo.bind();
@@ -282,7 +274,6 @@ void ExportThread::run() {
QPainter painter(&fbo_dev);
painter.beginNativePainting();
- int written_frame_audio_bytes = 0;
long file_audio_samples = 0;
while (panel_timeline->playhead < end && !fail) {
@@ -301,8 +292,9 @@ void ExportThread::run() {
memcpy(video_frame->data[0]+dst_index, flip_buffer+src_index, linesize);
}
- // change pixel format
- sws_scale(sws_ctx, video_frame->data, video_frame->linesize, 0, video_frame->height, sws_frame->data, sws_frame->linesize);
+ // change pixel format
+ sws_scale(sws_ctx, video_frame->data, video_frame->linesize, 0, video_frame->height, sws_frame->data, sws_frame->linesize);
+// qDebug() << video_frame->linesize[0] << sws_frame->linesize[0];
sws_frame->pts = round(timecode_secs/av_q2d(video_stream->time_base));
// send to encoder
@@ -310,23 +302,29 @@ void ExportThread::run() {
}
if (audio_enabled && !fail) {
// do we need to encode more audio samples?
- if (file_audio_samples <= (timecode_secs*audio_sampling_rate)) {
- uint8_t* cache = (reading_audio_cache_A) ? audio_cache_A : audio_cache_B;
- int copylen = qMin(aframe_bytes-written_frame_audio_bytes, audio_cache_size-audio_bytes_written);
- memcpy(audio_frame->data[0]+written_frame_audio_bytes, cache+audio_bytes_written, copylen);
- written_frame_audio_bytes += copylen;
- audio_bytes_written += copylen;
- if (written_frame_audio_bytes == aframe_bytes) {
- // convert to export sample format
- swr_convert_frame(swr_ctx, swr_frame, audio_frame);
- swr_frame->pts = file_audio_samples;
+ while (file_audio_samples <= (timecode_secs*audio_sampling_rate)) {
+ int adjusted_read = audio_ibuffer_read%audio_ibuffer_size;
+ int copylen = qMin(aframe_bytes, audio_ibuffer_size-adjusted_read);
+ memcpy(audio_frame->data[0], audio_ibuffer+adjusted_read, copylen);
+ memset(audio_ibuffer+adjusted_read, 0, copylen);
+ audio_ibuffer_read += copylen;
- // send to encoder
- if (!encode(fmt_ctx, acodec_ctx, swr_frame, &audio_pkt, audio_stream)) fail = true;
-
- file_audio_samples += swr_frame->nb_samples;
- written_frame_audio_bytes = 0;
+ if (copylen < aframe_bytes) {
+ // copy remainder
+ int remainder_len = aframe_bytes-copylen;
+ memcpy(audio_frame->data[0]+copylen, audio_ibuffer, remainder_len);
+ memset(audio_ibuffer, 0, remainder_len);
+ audio_ibuffer_read += remainder_len;
}
+
+ // convert to export sample format
+ swr_convert_frame(swr_ctx, swr_frame, audio_frame);
+ swr_frame->pts = file_audio_samples;
+
+ // send to encoder
+ if (!encode(fmt_ctx, acodec_ctx, swr_frame, &audio_pkt, audio_stream)) fail = true;
+
+ file_audio_samples += swr_frame->nb_samples;
}
}
emit progress_changed(((float) panel_timeline->playhead / (float) end) * 100);
diff --git a/olive.pro b/olive.pro
index a2cb46ce7..4a98ac142 100644
--- a/olive.pro
+++ b/olive.pro
@@ -69,7 +69,6 @@ HEADERS += \
playback/audio.h \
effects/effects.h \
io/config.h \
- ui/timeline-tools.h \
dialogs/newsequencedialog.h \
ui/viewerwidget.h \
ui/viewercontainer.h \
@@ -78,7 +77,8 @@ HEADERS += \
project/effect.h \
panels/panels.h \
playback/cacher.h \
- io/exportthread.h
+ io/exportthread.h \
+ ui/timelinetools.h
FORMS += \
mainwindow.ui \
diff --git a/olive.pro.user b/olive.pro.user
index e57423a29..3a7b3e899 100644
--- a/olive.pro.user
+++ b/olive.pro.user
@@ -1,6 +1,6 @@
-
+
EnvironmentId
diff --git a/panels/timeline.cpp b/panels/timeline.cpp
index 9c3056d6d..a9b3e15bc 100644
--- a/panels/timeline.cpp
+++ b/panels/timeline.cpp
@@ -69,11 +69,10 @@ void Timeline::seek(long p) {
Clip& c = sequence->get_clip(i);
c.reset_audio = true;
c.frame_sample_index = 0;
+ c.audio_buffer_write = 0;
}
- clear_cache(true, true);
- audio_bytes_written = 0;
- switch_audio_cache = true;
- reading_audio_cache_A = false;
+ clear_audio_ibuffer();
+ audio_ibuffer_read = 0;
playhead = p;
}
@@ -92,11 +91,7 @@ void Timeline::play() {
playback_timer.start();
start_msecs = QDateTime::currentMSecsSinceEpoch();
playback_updater.start();
- playing = true;
-
- if (switch_audio_cache) {
- // add something to pre-cache audio
- }
+ playing = true;
}
void Timeline::pause() {
diff --git a/panels/timeline.h b/panels/timeline.h
index f7b6aa3b3..66939775f 100644
--- a/panels/timeline.h
+++ b/panels/timeline.h
@@ -1,7 +1,7 @@
#ifndef TIMELINE_H
#define TIMELINE_H
-#include "ui/timeline-tools.h"
+#include "ui/timelinetools.h"
#include
#include
#include
diff --git a/panels/viewer.cpp b/panels/viewer.cpp
index d2a8698b3..fb0c35aab 100644
--- a/panels/viewer.cpp
+++ b/panels/viewer.cpp
@@ -29,10 +29,6 @@ Viewer::~Viewer()
delete ui;
}
-void Viewer::receiver() {
- qDebug() << "callback?";
-}
-
void Viewer::set_sequence(Sequence* s) {
bool null_sequence = (s == NULL);
sequence = s;
@@ -45,14 +41,13 @@ void Viewer::set_sequence(Sequence* s) {
ui->pushButton_4->setEnabled(!null_sequence);
ui->pushButton_5->setEnabled(!null_sequence);
+ init_audio(s);
+
if (!null_sequence) {
ui->glViewerPane->aspect_ratio = (float) sequence->width / (float) sequence->height;
- ui->glViewerPane->adjust();
+ ui->glViewerPane->adjust();
}
- init_audio(s);
- connect(audio_output, SIGNAL(notify()), this, SLOT(receiver()));
-
update();
}
diff --git a/panels/viewer.h b/panels/viewer.h
index f1681d6ca..ffcad1f4f 100644
--- a/panels/viewer.h
+++ b/panels/viewer.h
@@ -33,9 +33,7 @@ private slots:
void on_pushButton_4_clicked();
- void on_pushButton_3_clicked();
-
- void receiver();
+ void on_pushButton_3_clicked();
private:
Ui::Viewer *ui;
diff --git a/playback/audio.cpp b/playback/audio.cpp
index 33fc9a820..7de4a562c 100644
--- a/playback/audio.cpp
+++ b/playback/audio.cpp
@@ -13,24 +13,11 @@ QAudioOutput* audio_output;
QIODevice* audio_io_device;
bool audio_device_set = false;
-uint8_t* audio_cache_A = NULL;
-uint8_t* audio_cache_B = NULL;
-int audio_cache_size = 0;
-bool switch_audio_cache = true;
-bool reading_audio_cache_A = false;
-int audio_bytes_written = 0;
+qint8 audio_ibuffer[audio_ibuffer_size];
+int audio_ibuffer_read = 0;
+QVector audio_ibuffer_write;
void init_audio(Sequence* s) {
- if (audio_cache_A != NULL) {
- delete [] audio_cache_A;
- audio_cache_A = NULL;
- }
-
- if (audio_cache_B != NULL) {
- delete [] audio_cache_B;
- audio_cache_B = NULL;
- }
-
if (audio_device_set) {
audio_output->stop();
delete audio_output;
@@ -55,19 +42,11 @@ void init_audio(Sequence* s) {
audio_io_device = audio_output->start();
audio_device_set = true;
- audio_cache_size = av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(s->audio_layout), s->audio_frequency/8, AV_SAMPLE_FMT_S16, 1);
- audio_cache_A = new uint8_t[audio_cache_size];
- audio_cache_B = new uint8_t[audio_cache_size];
- clear_cache(true, true);
+ clear_audio_ibuffer();
}
}
}
-void clear_cache(bool clear_A, bool clear_B) {
- if (clear_A) {
- memset(audio_cache_A, 0, audio_cache_size);
- }
- if (clear_B) {
- memset(audio_cache_B, 0, audio_cache_size);
- }
+void clear_audio_ibuffer() {
+ memset(audio_ibuffer, 0, audio_ibuffer_size);
}
diff --git a/playback/audio.h b/playback/audio.h
index 093b4f0a1..555bc44b5 100644
--- a/playback/audio.h
+++ b/playback/audio.h
@@ -1,7 +1,7 @@
#ifndef AUDIO_H
#define AUDIO_H
-#include
+#include
class QAudioOutput;
class QIODevice;
@@ -11,13 +11,12 @@ struct Sequence;
extern QAudioOutput* audio_output;
extern QIODevice* audio_io_device;
-extern uint8_t* audio_cache_A;
-extern uint8_t* audio_cache_B;
-extern int audio_cache_size;
-extern int audio_bytes_written;
-extern bool switch_audio_cache;
-extern bool reading_audio_cache_A;
+#define audio_ibuffer_size 192000
+extern qint8 audio_ibuffer[audio_ibuffer_size];
+extern int audio_ibuffer_read;
+//extern QVector audio_ibuffer_write;
+void clear_audio_ibuffer();
+
void init_audio(Sequence* s);
-void clear_cache(bool clear_A, bool clear_B);
#endif // AUDIO_H
diff --git a/playback/cacher.cpp b/playback/cacher.cpp
index 8d68216ed..a83e6aaa4 100644
--- a/playback/cacher.cpp
+++ b/playback/cacher.cpp
@@ -16,46 +16,67 @@ extern "C" {
#include
-void cache_audio_worker(Clip* c, bool write_A) {
- // gets one frame worth of audio and sends it to the audio buffer
- AVFrame* frame = c->cache_A.frames[0];
- uint8_t* cache = (write_A) ? audio_cache_A : audio_cache_B;
+void cache_audio_worker(Clip* c) {
+ int written = 0;
+ int max_write = 16384;
+ while (written < max_write) {
+ // gets one frame worth of audio and sends it to the audio buffer
+ AVFrame* frame = c->cache_A.frames[0];
- int bytes_written = 0;
- int j = 0;
- while (bytes_written < audio_cache_size && !c->reached_end) {
- // is there audio left in the frame
- if (c->frame_sample_index == 0) {
- // no more audio left in frame, get a new one
- retrieve_next_frame_raw_data(c, frame);
- }
- if (!c->reached_end) {
- int nb_bytes = av_samples_get_buffer_size(NULL, frame->channels, frame->nb_samples, static_cast(frame->format), 1);
- int limit = std::min(c->frame_sample_index + audio_cache_size - bytes_written, nb_bytes);
- // perform all audio effects
+ if (c->frame_sample_index == 0) {
+ // no more audio left in frame, get a new one
+ if (!c->reached_end) {
+ retrieve_next_frame_raw_data(c, frame);
+ } else {
+ // set by retrieve_next_frame_raw_data indicating no more frames in file,
+ // but there still may be samples in swresample
+ swr_convert_frame(c->swr_ctx, frame, NULL);
+ }
+ }
+
+ if (frame->nb_samples == 0) {
+ written = max_write;
+ } else {
+ int nb_bytes = av_samples_get_buffer_size(NULL, frame->channels, frame->nb_samples, static_cast(frame->format), 1);
+
+ // perform all audio effects
for (int j=0;jeffects.size();j++) {
- c->effects.at(j)->process_audio(frame->data[0], limit);
- }
- // mix audio into cache
- for (int i=c->frame_sample_index;idata[0][i];
- j++;
- }
- bytes_written += limit - c->frame_sample_index;
- c->frame_sample_index = (limit == nb_bytes) ? 0 : limit;
- }
- }
+ c->effects.at(j)->process_audio(frame->data[0], nb_bytes);
+ }
+
+ if (c->audio_buffer_write == 0) c->audio_buffer_write = audio_ibuffer_read + 1024;
+ while (c->frame_sample_index < nb_bytes) {
+ if (c->audio_buffer_write >= audio_ibuffer_read+(audio_ibuffer_size/2)) {
+ written = max_write;
+ break;
+ } else {
+ audio_ibuffer[c->audio_buffer_write%audio_ibuffer_size] += frame->data[0][c->frame_sample_index];
+ c->audio_buffer_write++;
+ c->frame_sample_index++;
+ }
+ }
+ written += c->frame_sample_index;
+ if (c->frame_sample_index == nb_bytes) {
+ c->frame_sample_index = 0;
+ }
+ }
+ }
}
void cache_video_worker(Clip* c, long playhead, ClipCache* cache) {
- cache->mutex.lock();
+ cache->mutex.lock();
- cache->offset = playhead;
- for (size_t i=0;icache_size;i++) {
- retrieve_next_frame_raw_data(c, cache->frames[i]);
- }
- cache->written = true;
- cache->unread = true;
+ cache->offset = playhead;
+ if (!c->reached_end) {
+ for (size_t i=0;icache_size;i++) {
+ retrieve_next_frame_raw_data(c, cache->frames[i]);
+ if (c->reached_end) break;
+ }
+ }
+ cache->written = true;
+ cache->unread = true;
+ // setting the cache to written even if it hasn't reached_end prevents playback from
+ // signaling a seek/reset because it wasn't able to find the frame
cache->mutex.unlock();
}
@@ -81,7 +102,7 @@ void reset_cache(Clip* c, long target_frame) {
// play up to the frame we actually want
long retrieved_frame = 0;
AVFrame* temp = av_frame_alloc();
- do {
+ do {
retrieve_next_frame(c, temp);
if (retrieved_frame == 0) {
if (target_frame != 0) {
@@ -223,7 +244,7 @@ void open_clip_worker(Clip* clip) {
clip->sequence->audio_layout,
static_cast(sample_format),
clip->sequence->audio_frequency,
- clip->stream->codecpar->channel_layout,
+ clip->codecCtx->channel_layout,
static_cast(clip->stream->codecpar->format),
clip->stream->codecpar->sample_rate,
0,
@@ -266,13 +287,8 @@ void cache_clip_worker(Clip* clip, long playhead, bool write_A, bool write_B, bo
if (write_B) {
cache_video_worker(clip, playhead, &clip->cache_B);
}
- } else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
- if (write_A) {
- cache_audio_worker(clip, true);
- }
- if (write_B) {
- cache_audio_worker(clip, false);
- }
+ } else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+ cache_audio_worker(clip);
}
}
@@ -323,8 +339,8 @@ void Cacher::run() {
caching = true;
while (true) {
- clip->can_cache.wait(&clip->lock);
- if (!caching) {
+ clip->can_cache.wait(&clip->lock);
+ if (!caching) {
break;
} else {
cache_clip_worker(clip, playhead, write_A, write_B, reset);
diff --git a/playback/playback.cpp b/playback/playback.cpp
index b58725a77..070e9a4d3 100644
--- a/playback/playback.cpp
+++ b/playback/playback.cpp
@@ -34,7 +34,7 @@ void handle_media(Sequence* sequence, long playhead, bool multithreaded) {
// if thread is already working, we don't want to touch this,
// but we also don't want to hang the UI thread
if (!c.open) {
- if (c.lock.tryLock()) {
+ if (c.lock.tryLock()) {
open_clip(&c, multithreaded);
// add to current_clips, (insertion) sorted by track so composite them in order
@@ -229,13 +229,10 @@ float clip_frame_to_seconds(Clip* c, long clip_frame) {
int retrieve_next_frame(Clip* c, AVFrame* f) {
int result = 0;
- int receive_ret;
-
- // could be optimized if "linked stream" shares timeline_in and clip_in, only use one read_frame?
- // depends how much time av_read_frame needs, the decoding is probably far more consuming anyway
+ int receive_ret;
// do we need to retrieve a new packet for a new frame?
- while ((receive_ret = avcodec_receive_frame(c->codecCtx, f)) == AVERROR(EAGAIN)) {
+ while ((receive_ret = avcodec_receive_frame(c->codecCtx, f)) == AVERROR(EAGAIN)) {
int read_ret = 0;
do {
if (c->pkt_written) {
@@ -249,10 +246,9 @@ int retrieve_next_frame(Clip* c, AVFrame* f) {
int send_ret = avcodec_send_packet(c->codecCtx, c->pkt);
if (send_ret < 0) {
qDebug() << "[ERROR] Failed to send packet to decoder." << send_ret;
- result = send_ret;
- break;
+ return send_ret;
}
- } else {
+ } else {
if (read_ret != AVERROR_EOF) qDebug() << "[ERROR] Could not read frame." << read_ret;
return read_ret; // skips trying to find a frame at all
}
@@ -266,21 +262,26 @@ int retrieve_next_frame(Clip* c, AVFrame* f) {
}
void retrieve_next_frame_raw_data(Clip* c, AVFrame* output) {
- int ret = retrieve_next_frame(c, c->frame);
- if (ret >= 0) {
- if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
- sws_scale(c->sws_ctx, c->frame->data, c->frame->linesize, 0, c->stream->codecpar->height, output->data, output->linesize);
- } else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
- ret = swr_convert_frame(c->swr_ctx, output, c->frame);
- if (ret < 0) {
- qDebug() << "[ERROR] Failed to resample audio." << ret;
- }
- }
- } else if (ret == AVERROR_EOF) {
- c->reached_end = true;
- } else {
- qDebug() << "[WARNING] Raw frame data could not be retrieved." << ret;
- }
+ if (c->reached_end) {
+ qDebug() << "[WARNING] Attempted to retrieve frame of stream with no frames left";
+ } else {
+ int ret = retrieve_next_frame(c, c->frame);
+ if (ret >= 0) {
+ if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+ sws_scale(c->sws_ctx, c->frame->data, c->frame->linesize, 0, c->stream->codecpar->height, output->data, output->linesize);
+ } else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+ ret = swr_convert_frame(c->swr_ctx, output, c->frame);
+ if (ret < 0) {
+ qDebug() << "[ERROR] Failed to resample audio." << ret;
+ }
+ }
+ } else if (ret == AVERROR_EOF) {
+// qDebug() << "reached end triggered" << c->track;
+ c->reached_end = true;
+ } else {
+ qDebug() << "[WARNING] Raw frame data could not be retrieved." << ret;
+ }
+ }
}
bool is_clip_active(Clip* c, long playhead) {
diff --git a/project/clip.cpp b/project/clip.cpp
index 650513f43..93d0878c5 100644
--- a/project/clip.cpp
+++ b/project/clip.cpp
@@ -52,7 +52,7 @@ void Clip::init() {
}
void Clip::reset() {
- cache_size = cache_A.offset = cache_B.offset = open = pkt_written = cache_A.written = cache_B.written = cache_A.unread = cache_B.unread = reached_end = reset_audio = frame_sample_index = 0;
+ cache_size = cache_A.offset = cache_B.offset = open = pkt_written = cache_A.written = cache_B.written = cache_A.unread = cache_B.unread = reached_end = reset_audio = frame_sample_index = audio_buffer_write = 0;
texture_frame = -1;
formatCtx = NULL;
stream = NULL;
diff --git a/project/clip.h b/project/clip.h
index 50708e357..bd0f1dc35 100644
--- a/project/clip.h
+++ b/project/clip.h
@@ -89,6 +89,7 @@ struct Clip
// audio playback variables
SwrContext* swr_ctx;
int frame_sample_index;
+ int audio_buffer_write;
bool reset_audio;
};
diff --git a/project/effect.cpp b/project/effect.cpp
index cacad5fee..0d505e3b1 100644
--- a/project/effect.cpp
+++ b/project/effect.cpp
@@ -21,5 +21,5 @@ Effect* Effect::copy() {
return e;
}
-void Effect::process_gl(int* anchor_x, int* anchor_y) {}
-void Effect::process_audio(uint8_t* samples, int nb_bytes) {}
+void Effect::process_gl(int*, int*) {}
+void Effect::process_audio(uint8_t*, int) {}
diff --git a/ui/timeline-tools.h b/ui/timeline-tools.h
deleted file mode 100644
index 28cdb10da..000000000
--- a/ui/timeline-tools.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef TIMELINETOOLS_H
-#define TIMELINETOOLS_H
-
-enum TimelineTools {
- TIMELINE_TOOL_POINTER,
- TIMELINE_TOOL_EDIT,
- TIMELINE_TOOL_RAZOR,
- TIMELINE_TOOL_RIPPLE,
- TIMELINE_TOOL_ROLLING,
- TIMELINE_TOOL_SLIP,
- TIMELINE_TOOL_HAND,
- TIMELINE_TOOL_ZOOM
-};
-
-#endif // TIMELINETOOLS_H
diff --git a/ui/timelinetools.h b/ui/timelinetools.h
new file mode 100644
index 000000000..74f54fb9a
--- /dev/null
+++ b/ui/timelinetools.h
@@ -0,0 +1,13 @@
+#ifndef TIMELINETOOLS_H
+#define TIMELINETOOLS_H
+
+#define TIMELINE_TOOL_POINTER 0
+#define TIMELINE_TOOL_EDIT 1
+#define TIMELINE_TOOL_RAZOR 2
+#define TIMELINE_TOOL_RIPPLE 3
+#define TIMELINE_TOOL_ROLLING 4
+#define TIMELINE_TOOL_SLIP 5
+#define TIMELINE_TOOL_HAND 6
+#define TIMELINE_TOOL_ZOOM 7
+
+#endif // TIMELINETOOLS_H
diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp
index 03ece55ad..743aae638 100644
--- a/ui/timelinewidget.cpp
+++ b/ui/timelinewidget.cpp
@@ -24,9 +24,7 @@ TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent)
{
bottom_align = false;
setMouseTracking(true);
- track_height = 40;
-
- clip_pixmap = NULL;
+ track_height = 40;
setAcceptDrops(true);
}
@@ -35,6 +33,10 @@ bool same_sign(int a, int b) {
return (a < 0) == (b < 0);
}
+void TimelineWidget::resizeEvent(QResizeEvent*) {
+ if (panel_timeline->sequence != NULL) redraw_clips();
+}
+
void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
if (static_cast(event->source()) == panel_project->source_table) {
QPoint pos = event->pos();
@@ -77,7 +79,7 @@ void TimelineWidget::dragMoveEvent(QDragMoveEvent *event) {
}
}
-void TimelineWidget::dragLeaveEvent(QDragLeaveEvent *event) {
+void TimelineWidget::dragLeaveEvent(QDragLeaveEvent*) {
if (panel_timeline->importing) {
panel_timeline->ghosts.clear();
panel_timeline->importing = false;
@@ -324,7 +326,6 @@ bool subvalidate_snapping(Ghost& g, long* frame_diff, long snap_point) {
}
void validate_snapping(Ghost& g, long* frame_diff) {
- long validator;
panel_timeline->snapped = false;
if (panel_timeline->snapping) {
if (!subvalidate_snapping(g, frame_diff, panel_timeline->playhead)) {
@@ -659,15 +660,13 @@ int color_brightness(int r, int g, int b) {
}
void TimelineWidget::redraw_clips() {
- // Draw clips
- if (clip_pixmap != NULL) delete clip_pixmap;
-
+ // Draw clips
int panel_width = getScreenPointFromFrame(panel_timeline->sequence->getEndFrame()) + 100;
setMinimumWidth(panel_width);
- clip_pixmap = new QPixmap(panel_width, height());
- clip_pixmap->fill(Qt::transparent);
- QPainter clip_painter(clip_pixmap);
+ clip_pixmap = QPixmap(panel_width, height());
+ clip_pixmap.fill(Qt::transparent);
+ QPainter clip_painter(&clip_pixmap);
int video_track_limit = 0;
int audio_track_limit = 0;
for (int i=0;isequence->clip_count();i++) {
@@ -726,7 +725,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
if (panel_timeline->sequence != NULL) {
QPainter p(this);
- if (clip_pixmap != NULL) p.drawPixmap(0, 0, minimumWidth(), height(), *clip_pixmap);
+ p.drawPixmap(0, 0, minimumWidth(), height(), clip_pixmap);
// Draw selections
for (int i=0;iselections.size();i++) {
diff --git a/ui/timelinewidget.h b/ui/timelinewidget.h
index fb14a3bb6..a743884ff 100644
--- a/ui/timelinewidget.h
+++ b/ui/timelinewidget.h
@@ -2,7 +2,7 @@
#define TIMELINEWIDGET_H
#include
-#include "timeline-tools.h"
+#include "timelinetools.h"
#define GHOST_THICKNESS 2 // thiccccc
#define CLIP_TEXT_PADDING 3
@@ -19,9 +19,10 @@ public:
bool bottom_align;
- void redraw_clips();
+ void redraw_clips();
protected:
void paintEvent(QPaintEvent*) override;
+ void resizeEvent(QResizeEvent*) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
@@ -45,12 +46,15 @@ private:
QList pre_clips;
QList post_clips;
- QPixmap* clip_pixmap;
+ QPixmap clip_pixmap;
// QPixmap selection_pixmap;
signals:
public slots:
+
+private slots:
+
};
#endif // TIMELINEWIDGET_H
diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp
index 270145d50..27d8e7f89 100644
--- a/ui/viewerwidget.cpp
+++ b/ui/viewerwidget.cpp
@@ -17,12 +17,10 @@ extern "C" {
ViewerWidget::ViewerWidget(QWidget *parent) : QOpenGLWidget(parent)
{
- multithreaded = true;
+ multithreaded = true;
enable_paint = true;
force_audio = false;
- audio_bytes_written = 0;
-
QSurfaceFormat format;
format.setDepthBufferSize(24);
setFormat(format);
@@ -67,17 +65,6 @@ void ViewerWidget::paintGL()
bool render_audio = (panel_timeline->playing || force_audio);
- // switch_cache
- if (render_audio && audio_bytes_written == audio_cache_size) {
- switch_audio_cache = true;
-
- reading_audio_cache_A = !reading_audio_cache_A;
- audio_bytes_written = 0;
- clear_cache(!reading_audio_cache_A, reading_audio_cache_A);
- }
-
-// qDebug() << audio_bytes_written << "/" << audio_cache_size;
-
cc_lock.lock();
for (int i=0;itexture->release();
}
- } else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
- playhead >= c->timeline_in &&
- render_audio &&
- !c->reached_end &&
- (switch_audio_cache || c->reset_audio)) {
- // TODO doesn't affect new clips appearing in the timeline (they'll ALWAYS end up in the other cache with a 1/8 sec delay)
-
- // cache audio
- if (c->lock.tryLock()) {
- // clip is not caching, start cache
- c->lock.unlock();
-
- cache_clip(c, playhead, !reading_audio_cache_A, reading_audio_cache_A, c->reset_audio);
- }
+ } else if (render_audio &&
+ c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
+ playhead >= c->timeline_in &&
+ c->lock.tryLock()) {
+ // clip is not caching, start caching audio
+ c->lock.unlock();
+ cache_clip(c, playhead, false, false, c->reset_audio);
}
}
- }
+ }
- if (render_audio) {
- switch_audio_cache = false;
-
- if (audio_cache_A != NULL && audio_bytes_written < audio_cache_size) {
- // send cached/buffered audio to QIODevice/QAudioOutput
- uint8_t* cache = reading_audio_cache_A ? audio_cache_A : audio_cache_B;
- if (panel_timeline->playing) {
- int max_w = audio_cache_size-audio_bytes_written;
- int w = audio_io_device->write((const char*) cache+audio_bytes_written, max_w);
- qDebug() << w << max_w;
- audio_bytes_written += w;
- }
+ if (panel_timeline->playing) {
+ int adjusted_read_index = audio_ibuffer_read%audio_ibuffer_size;
+ int max_write = audio_ibuffer_size - adjusted_read_index;
+ int actual_write = audio_io_device->write((const char*) audio_ibuffer+adjusted_read_index, max_write);
+ memset(audio_ibuffer+adjusted_read_index, 0, actual_write);
+ audio_ibuffer_read += actual_write;
+ if (actual_write == max_write) {
+ // got all the bytes, write again
+ actual_write = audio_io_device->write((const char*) audio_ibuffer, audio_ibuffer_size);
+ memset(audio_ibuffer, 0, actual_write);
+ audio_ibuffer_read += actual_write;
}
- }
+ }
cc_lock.unlock();