fixed various issues with threading
This commit is contained in:
+20
-20
@@ -153,12 +153,12 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
if (type == LOAD_TYPE_VERSION) {
|
||||
int proj_version = stream.readElementText().toInt();
|
||||
if (proj_version < MIN_SAVE_VERSION && proj_version > SAVE_VERSION) {
|
||||
if (QMessageBox::warning(
|
||||
mainWindow,
|
||||
tr("Version Mismatch"),
|
||||
tr("This project was saved in a different version of Olive and may not be fully compatible with this version. Would you like to attempt loading it anyway?"),
|
||||
QMessageBox::Yes,
|
||||
QMessageBox::No) == QMessageBox::No) {
|
||||
if (QMessageBox::warning(
|
||||
mainWindow,
|
||||
tr("Version Mismatch"),
|
||||
tr("This project was saved in a different version of Olive and may not be fully compatible with this version. Would you like to attempt loading it anyway?"),
|
||||
QMessageBox::Yes,
|
||||
QMessageBox::No) == QMessageBox::No) {
|
||||
show_err = false;
|
||||
return false;
|
||||
}
|
||||
@@ -444,11 +444,11 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
if (!found) {
|
||||
correct_clip->linked.removeAt(j);
|
||||
j--;
|
||||
if (QMessageBox::warning(mainWindow,
|
||||
tr("Invalid Clip Link"),
|
||||
tr("This project contains an invalid clip link. It may be corrupt. Would you like to continue loading it?"),
|
||||
QMessageBox::Yes,
|
||||
QMessageBox::No) == QMessageBox::No) {
|
||||
if (QMessageBox::warning(mainWindow,
|
||||
tr("Invalid Clip Link"),
|
||||
tr("This project contains an invalid clip link. It may be corrupt. Would you like to continue loading it?"),
|
||||
QMessageBox::Yes,
|
||||
QMessageBox::No) == QMessageBox::No) {
|
||||
delete s;
|
||||
return false;
|
||||
}
|
||||
@@ -601,7 +601,7 @@ void LoadThread::run() {
|
||||
xml_error = false;
|
||||
if (show_err) emit error();
|
||||
} else if (stream.hasError()) {
|
||||
error_str = tr("%1 - Line: %2 Col: %3").arg(stream.errorString(), QString::number(stream.lineNumber()), QString::number(stream.columnNumber()));
|
||||
error_str = tr("%1 - Line: %2 Col: %3").arg(stream.errorString(), QString::number(stream.lineNumber()), QString::number(stream.columnNumber()));
|
||||
xml_error = true;
|
||||
emit error();
|
||||
cont = false;
|
||||
@@ -641,15 +641,15 @@ void LoadThread::cancel() {
|
||||
void LoadThread::error_func() {
|
||||
if (xml_error) {
|
||||
qCritical() << "Error parsing XML." << error_str;
|
||||
QMessageBox::critical(mainWindow,
|
||||
tr("XML Parsing Error"),
|
||||
tr("Couldn't load '%1'. %2").arg(project_url, error_str),
|
||||
QMessageBox::Ok);
|
||||
QMessageBox::critical(mainWindow,
|
||||
tr("XML Parsing Error"),
|
||||
tr("Couldn't load '%1'. %2").arg(project_url, error_str),
|
||||
QMessageBox::Ok);
|
||||
} else {
|
||||
QMessageBox::critical(mainWindow,
|
||||
tr("Project Load Error"),
|
||||
tr("Error loading project: %1").arg(error_str),
|
||||
QMessageBox::Ok);
|
||||
QMessageBox::critical(mainWindow,
|
||||
tr("Project Load Error"),
|
||||
tr("Error loading project: %1").arg(error_str),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,8 @@ SOURCES += \
|
||||
dialogs/texteditdialog.cpp \
|
||||
dialogs/debugdialog.cpp \
|
||||
ui/renderthread.cpp \
|
||||
ui/renderfunctions.cpp
|
||||
ui/renderfunctions.cpp \
|
||||
ui/viewerwindow.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
@@ -220,7 +221,8 @@ HEADERS += \
|
||||
dialogs/texteditdialog.h \
|
||||
dialogs/debugdialog.h \
|
||||
ui/renderthread.h \
|
||||
ui/renderfunctions.h
|
||||
ui/renderfunctions.h \
|
||||
ui/viewerwindow.h
|
||||
|
||||
FORMS +=
|
||||
|
||||
|
||||
+1
-1
@@ -913,7 +913,7 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only,
|
||||
}
|
||||
// save_folder(stream, item, type, set_ids_only);
|
||||
} else {
|
||||
int folder = (m->parentItem() != nullptr) ? m->parentItem()->temp_id : 0;
|
||||
int folder = m->parentItem()->temp_id;
|
||||
if (type == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* f = m->to_footage();
|
||||
f->save_id = media_id;
|
||||
|
||||
+9
-7
@@ -44,7 +44,7 @@ Viewer::Viewer(QWidget *parent) :
|
||||
seq(nullptr),
|
||||
created_sequence(false),
|
||||
cue_recording_internal(false),
|
||||
panel_name(tr("Viewer: ")),
|
||||
panel_name(tr("Viewer: ")),
|
||||
minimum_zoom(1.0)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
@@ -107,7 +107,9 @@ void Viewer::reset_all_audio() {
|
||||
|
||||
for (int i=0;i<seq->clips.size();i++) {
|
||||
Clip* c = seq->clips.at(i);
|
||||
if (c != nullptr) c->reset_audio();
|
||||
if (c != nullptr) {
|
||||
c->reset_audio();
|
||||
}
|
||||
}
|
||||
}
|
||||
clear_audio_ibuffer();
|
||||
@@ -251,9 +253,9 @@ void Viewer::seek(long p) {
|
||||
update_fx = true;
|
||||
}
|
||||
}
|
||||
update_parents(update_fx);
|
||||
reset_all_audio();
|
||||
audio_scrub = true;
|
||||
update_parents(update_fx);
|
||||
}
|
||||
|
||||
void Viewer::go_to_start() {
|
||||
@@ -439,7 +441,7 @@ void Viewer::resizeEvent(QResizeEvent *) {
|
||||
|
||||
void Viewer::update_viewer() {
|
||||
update_header_zoom();
|
||||
viewer_widget->update();
|
||||
viewer_widget->frame_update();
|
||||
if (seq != nullptr) update_playhead_timecode(seq->playhead);
|
||||
update_end_timecode();
|
||||
}
|
||||
@@ -675,7 +677,7 @@ void Viewer::set_media(Media* m) {
|
||||
viewer_widget->waveform = true;
|
||||
viewer_widget->waveform_clip = c;
|
||||
viewer_widget->waveform_ms = &audio_stream;
|
||||
viewer_widget->update();
|
||||
viewer_widget->frame_update();
|
||||
}
|
||||
} else {
|
||||
seq->audio_frequency = 48000;
|
||||
@@ -785,12 +787,12 @@ void Viewer::set_sequence(bool main, Sequence *s) {
|
||||
update_playhead_timecode(0);
|
||||
update_end_timecode();
|
||||
|
||||
setWindowTitle(panel_name + tr("(none)"));
|
||||
setWindowTitle(panel_name + tr("(none)"));
|
||||
}
|
||||
|
||||
update_header_zoom();
|
||||
|
||||
viewer_widget->update();
|
||||
viewer_widget->frame_update();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
+4
-2
@@ -102,8 +102,10 @@ void stop_audio() {
|
||||
|
||||
void clear_audio_ibuffer() {
|
||||
if (audio_thread != nullptr) audio_thread->lock.lock();
|
||||
audio_write_lock.lock();
|
||||
memset(audio_ibuffer, 0, audio_ibuffer_size);
|
||||
audio_ibuffer_read = 0;
|
||||
audio_write_lock.unlock();
|
||||
if (audio_thread != nullptr) audio_thread->lock.unlock();
|
||||
}
|
||||
|
||||
@@ -292,7 +294,7 @@ bool start_recording() {
|
||||
return false;
|
||||
}
|
||||
|
||||
QString audio_path = project_url + " " + QCoreApplication::translate("Audio", "Audio");
|
||||
QString audio_path = project_url + " " + QCoreApplication::translate("Audio", "Audio");
|
||||
QDir audio_dir(audio_path);
|
||||
if (!audio_dir.exists() && !audio_dir.mkpath(".")) {
|
||||
qCritical() << "Failed to create audio directory";
|
||||
@@ -303,7 +305,7 @@ bool start_recording() {
|
||||
int file_number = 0;
|
||||
do {
|
||||
file_number++;
|
||||
audio_filename = audio_path + "/" + QCoreApplication::translate("Audio", "Recording") + " " + QString::number(file_number) + ".wav";
|
||||
audio_filename = audio_path + "/" + QCoreApplication::translate("Audio", "Recording") + " " + QString::number(file_number) + ".wav";
|
||||
} while (QFile(audio_filename).exists());
|
||||
|
||||
output_recording.setFileName(audio_filename);
|
||||
|
||||
+8
-2
@@ -376,11 +376,13 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
qint16 new_sample = static_cast<qint16>((frame->data[0][c->frame_sample_index+1] & 0xFF) << 8 | (frame->data[0][c->frame_sample_index] & 0xFF));
|
||||
qint16 mixed_sample = mix_audio_sample(old_sample, new_sample);
|
||||
|
||||
audio_ibuffer[upper_byte_index] = static_cast<quint8>((mixed_sample >> 8) & 0xFF);
|
||||
audio_ibuffer[lower_byte_index] = static_cast<quint8>(mixed_sample & 0xFF);
|
||||
audio_ibuffer[upper_byte_index] = quint8((mixed_sample >> 8) & 0xFF);
|
||||
audio_ibuffer[lower_byte_index] = quint8(mixed_sample & 0xFF);
|
||||
|
||||
c->audio_buffer_write+=2;
|
||||
c->frame_sample_index+=2;
|
||||
|
||||
if (c->audio_reset) break;
|
||||
}
|
||||
|
||||
#ifdef AUDIOWARNINGS
|
||||
@@ -389,6 +391,8 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
|
||||
audio_write_lock.unlock();
|
||||
|
||||
if (c->audio_reset) return;
|
||||
|
||||
if (scrubbing) {
|
||||
if (audio_thread != nullptr) audio_thread->notifyReceiver();
|
||||
}
|
||||
@@ -558,7 +562,9 @@ void reset_cache(Clip* c, long target_frame) {
|
||||
} else {
|
||||
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
// clear current queue
|
||||
c->queue_lock.lock();
|
||||
c->queue_clear();
|
||||
c->queue_lock.unlock();
|
||||
|
||||
// seeks to nearest keyframe (target_frame represents internal clip frame)
|
||||
int64_t target_ts = seconds_to_timestamp(c, playhead_to_clip_seconds(c, target_frame));
|
||||
|
||||
@@ -158,8 +158,10 @@ void get_clip_frame(Clip* c, long playhead) {
|
||||
#endif
|
||||
closest_frame = i;
|
||||
break;
|
||||
} else if (c->queue.at(i)->pts > c->queue.at(closest_frame)->pts && c->queue.at(i)->pts < target_pts) {
|
||||
closest_frame = i;
|
||||
} else {
|
||||
if (c->queue.at(i)->pts > c->queue.at(closest_frame)->pts && c->queue.at(i)->pts < target_pts) {
|
||||
closest_frame = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +249,7 @@ void get_clip_frame(Clip* c, long playhead) {
|
||||
if (target_frame == nullptr || reset) {
|
||||
// reset cache
|
||||
texture_failed = true;
|
||||
qInfo() << "Frame queue couldn't keep up - either the user seeked or the system is overloaded (queue size:" << c->queue.size() << ")";
|
||||
// qInfo() << "Frame queue couldn't keep up - either the user seeked or the system is overloaded (queue size:" << c->queue.size() << ")";
|
||||
}
|
||||
|
||||
if (target_frame != nullptr) {
|
||||
|
||||
@@ -7,14 +7,19 @@
|
||||
#include "debug.h"
|
||||
|
||||
ProjectModel::ProjectModel(QObject *parent) : QAbstractItemModel(parent), root_item(nullptr) {
|
||||
root_item = new Media(0);
|
||||
root_item->root = true;
|
||||
make_root();
|
||||
}
|
||||
|
||||
ProjectModel::~ProjectModel() {
|
||||
destroy_root();
|
||||
}
|
||||
|
||||
void ProjectModel::make_root() {
|
||||
root_item = new Media(nullptr);
|
||||
root_item->temp_id = 0;
|
||||
root_item->root = true;
|
||||
}
|
||||
|
||||
void ProjectModel::destroy_root() {
|
||||
if (panel_sequence_viewer != nullptr) panel_sequence_viewer->viewer_widget->delete_function();
|
||||
if (panel_footage_viewer != nullptr) panel_footage_viewer->viewer_widget->delete_function();
|
||||
@@ -27,8 +32,7 @@ void ProjectModel::destroy_root() {
|
||||
void ProjectModel::clear() {
|
||||
beginResetModel();
|
||||
destroy_root();
|
||||
root_item = new Media(0);
|
||||
root_item->root = true;
|
||||
make_root();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,10 @@ class ProjectModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProjectModel(QObject* parent = 0);
|
||||
ProjectModel(QObject* parent = nullptr);
|
||||
~ProjectModel() override;
|
||||
|
||||
void make_root();
|
||||
void destroy_root();
|
||||
void clear();
|
||||
Media* get_root();
|
||||
|
||||
@@ -425,7 +425,7 @@ GLuint compose_sequence(Viewer* viewer,
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // unbind texture
|
||||
|
||||
// TODO restore this function
|
||||
/*if (gizmos != nullptr && !drawn_gizmos && nests.isEmpty()) {
|
||||
/*if ((*gizmos) != nullptr && !drawn_gizmos && nests.isEmpty()) {
|
||||
(*gizmos)->gizmo_draw(timecode, coords); // set correct gizmo coords
|
||||
(*gizmos)->gizmo_world_to_screen();
|
||||
|
||||
|
||||
+24
-5
@@ -7,12 +7,16 @@
|
||||
|
||||
#include "ui/renderfunctions.h"
|
||||
#include "playback/playback.h"
|
||||
#include "project/sequence.h"
|
||||
|
||||
RenderThread::RenderThread() :
|
||||
share_ctx(nullptr),
|
||||
ctx(nullptr),
|
||||
frameBuffer(0),
|
||||
texColorBuffer(0)
|
||||
texColorBuffer(0),
|
||||
tex_width(-1),
|
||||
tex_height(-1),
|
||||
queued(false)
|
||||
{
|
||||
surface.create();
|
||||
}
|
||||
@@ -27,7 +31,10 @@ void RenderThread::run() {
|
||||
bool running = true;
|
||||
|
||||
while (running) {
|
||||
waitCond.wait(&mutex);
|
||||
if (!queued) {
|
||||
waitCond.wait(&mutex);
|
||||
}
|
||||
queued = false;
|
||||
|
||||
if (share_ctx != nullptr) {
|
||||
if (ctx == nullptr) {
|
||||
@@ -48,12 +55,20 @@ void RenderThread::run() {
|
||||
ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer);
|
||||
|
||||
// gen texture
|
||||
if (texColorBuffer == 0) {
|
||||
if (texColorBuffer == 0 || tex_width != seq->width || tex_height != seq->height) {\
|
||||
if (texColorBuffer > 0) {
|
||||
ctx->functions()->glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0
|
||||
);
|
||||
glDeleteTextures(1, &texColorBuffer);
|
||||
}
|
||||
glGenTextures(1, &texColorBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, texColorBuffer);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGB, 1920, 1080, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr
|
||||
GL_TEXTURE_2D, 0, GL_RGB, seq->width, seq->height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr
|
||||
);
|
||||
tex_width = seq->width;
|
||||
tex_height = seq->height;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
ctx->functions()->glFramebufferTexture2D(
|
||||
@@ -70,12 +85,15 @@ void RenderThread::run() {
|
||||
|
||||
// release
|
||||
ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
emit ready();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx != nullptr) {
|
||||
if (frameBuffer != 0) ctx->functions()->glDeleteFramebuffers(1, &frameBuffer);
|
||||
if (texColorBuffer > 0) glDeleteTextures(1, &texColorBuffer);
|
||||
if (frameBuffer > 0) ctx->functions()->glDeleteFramebuffers(1, &frameBuffer);
|
||||
ctx->doneCurrent();
|
||||
delete ctx;
|
||||
}
|
||||
@@ -110,5 +128,6 @@ void RenderThread::paint() {
|
||||
void RenderThread::start_render(QOpenGLContext *share, Sequence *s, int idivider) {
|
||||
share_ctx = share;
|
||||
seq = s;
|
||||
queued = true;
|
||||
waitCond.wakeAll();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
struct Sequence;
|
||||
|
||||
class RenderThread : public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
RenderThread();
|
||||
~RenderThread();
|
||||
@@ -20,6 +21,8 @@ public:
|
||||
GLuint texColorBuffer;
|
||||
void paint();
|
||||
void start_render(QOpenGLContext* share, Sequence* s, int idivider = 0);
|
||||
signals:
|
||||
void ready();
|
||||
private:
|
||||
QWaitCondition waitCond;
|
||||
QOffscreenSurface surface;
|
||||
@@ -27,6 +30,9 @@ private:
|
||||
QOpenGLContext* ctx;
|
||||
Sequence* seq;
|
||||
int divider;
|
||||
int tex_width;
|
||||
int tex_height;
|
||||
bool queued;
|
||||
};
|
||||
|
||||
#endif // RENDERTHREAD_H
|
||||
|
||||
+160
-60
@@ -23,6 +23,8 @@
|
||||
#include "ui/timelinewidget.h"
|
||||
#include "ui/renderfunctions.h"
|
||||
#include "ui/renderthread.h"
|
||||
#include "Ui/viewerwindow.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QAudioOutput>
|
||||
@@ -39,6 +41,8 @@
|
||||
#include <QDesktopWidget>
|
||||
#include <QInputDialog>
|
||||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
#include <QMessageBox>
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
@@ -53,7 +57,8 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
dragging(false),
|
||||
gizmos(nullptr),
|
||||
selected_gizmo(nullptr),
|
||||
just_repaint(false)
|
||||
just_repaint(false),
|
||||
window(nullptr)
|
||||
{
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
@@ -62,15 +67,19 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
format.setDepthBufferSize(24);
|
||||
setFormat(format);
|
||||
|
||||
// error handler - retries after 50ms if we couldn't get the entire image
|
||||
retry_timer.setInterval(50);
|
||||
connect(&retry_timer, SIGNAL(timeout()), this, SLOT(retry()));
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu()));
|
||||
|
||||
renderer = new RenderThread();
|
||||
renderer->start(QThread::HighPriority);
|
||||
connect(renderer, SIGNAL(ready()), this, SLOT(queue_repaint()));
|
||||
}
|
||||
|
||||
ViewerWidget::~ViewerWidget() {
|
||||
if (window != nullptr) {
|
||||
window->close();
|
||||
delete window;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::delete_function() {
|
||||
@@ -95,8 +104,18 @@ void ViewerWidget::show_context_menu() {
|
||||
QAction* save_frame_as_image = menu.addAction(tr("Save Frame as Image..."));
|
||||
connect(save_frame_as_image, SIGNAL(triggered(bool)), this, SLOT(save_frame()));
|
||||
|
||||
QAction* show_fullscreen_action = menu.addAction(tr("Show Fullscreen"));
|
||||
connect(show_fullscreen_action, SIGNAL(triggered()), this, SLOT(show_fullscreen()));
|
||||
/*QAction* show_fullscreen_action = menu.addAction(tr("Show Fullscreen"));
|
||||
connect(show_fullscreen_action, SIGNAL(triggered()), this, SLOT(show_fullscreen()));*/
|
||||
QMenu* fullscreen_menu = menu.addMenu(tr("Show Fullscreen"));
|
||||
QList<QScreen*> screens = QGuiApplication::screens();
|
||||
for (int i=0;i<screens.size();i++) {
|
||||
QAction* screen_action = fullscreen_menu->addAction(tr("Screen %1: %2x%3").arg(
|
||||
QString::number(i),
|
||||
QString::number(screens.at(i)->size().width()),
|
||||
QString::number(screens.at(i)->size().height())));
|
||||
screen_action->setData(i);
|
||||
}
|
||||
connect(fullscreen_menu, SIGNAL(triggered(QAction*)), this, SLOT(fullscreen_menu_action(QAction*)));
|
||||
|
||||
QMenu zoom_menu(tr("Zoom"));
|
||||
QAction* fit_zoom = zoom_menu.addAction(tr("Fit"));
|
||||
@@ -153,8 +172,20 @@ void ViewerWidget::save_frame() {
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::show_fullscreen() {
|
||||
showFullScreen();
|
||||
void ViewerWidget::queue_repaint() {
|
||||
just_repaint = true;
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewerWidget::fullscreen_menu_action(QAction *action) {
|
||||
if (window == nullptr) {
|
||||
QMessageBox::critical(this, "Error", "Failed to create viewer window");
|
||||
} else {
|
||||
QScreen* selected_screen = QGuiApplication::screens().at(action->data().toInt());
|
||||
window->showFullScreen();
|
||||
window->setGeometry(selected_screen->geometry());
|
||||
// window->show();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::set_fit_zoom() {
|
||||
@@ -193,19 +224,41 @@ void ViewerWidget::initializeGL() {
|
||||
|
||||
connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(delete_function()), Qt::DirectConnection);
|
||||
|
||||
retry_timer.start();
|
||||
if (window != nullptr) {
|
||||
delete window;
|
||||
}
|
||||
window = new ViewerWindow(context());
|
||||
|
||||
// retry_timer.start();
|
||||
}
|
||||
|
||||
void ViewerWidget::frame_update() {
|
||||
if (viewer->seq != nullptr) {
|
||||
gizmos = nullptr;
|
||||
drawn_gizmos = false;
|
||||
force_quit = false;
|
||||
|
||||
bool render_audio = (viewer->playing || rendering);
|
||||
|
||||
// send context to other thread for drawing
|
||||
doneCurrent();
|
||||
renderer->start_render(context(), viewer->seq);
|
||||
|
||||
// render the audio
|
||||
QVector<Clip*> nests;
|
||||
compose_sequence(viewer, context(), viewer->seq, nests, false, render_audio, &gizmos);
|
||||
}
|
||||
}
|
||||
|
||||
//void ViewerWidget::resizeGL(int w, int h)
|
||||
//{
|
||||
//}
|
||||
|
||||
void ViewerWidget::paintEvent(QPaintEvent *e) {
|
||||
if (!rendering && context()->thread() == this->thread()) {
|
||||
makeCurrent();
|
||||
/*void ViewerWidget::paintEvent(QPaintEvent *e) {
|
||||
if (!rendering) {
|
||||
QOpenGLWidget::paintEvent(e);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
void ViewerWidget::seek_from_click(int x) {
|
||||
viewer->seek(getFrameFromScreenPoint(waveform_zoom, x+waveform_scroll));
|
||||
@@ -393,8 +446,51 @@ void ViewerWidget::drawTitleSafeArea() {
|
||||
}
|
||||
|
||||
void ViewerWidget::paintGL() {
|
||||
retry_timer.stop();
|
||||
if (renderer->mutex.tryLock(10)) {
|
||||
makeCurrent();
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->texColorBuffer);
|
||||
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 1, 1, 0, -1, 1);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glVertex2f(0, 0);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(0, 1);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex2f(1, 1);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex2f(1, 0);
|
||||
glTexCoord2f(0, 1);
|
||||
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (window != nullptr && window->isVisible()) {
|
||||
window->set_texture(renderer->texColorBuffer, double(viewer->seq->width)/double(viewer->seq->height));
|
||||
}
|
||||
|
||||
renderer->mutex.unlock();
|
||||
|
||||
if (texture_failed) {
|
||||
doneCurrent();
|
||||
renderer->start_render(context(), viewer->seq);
|
||||
}
|
||||
}
|
||||
|
||||
// retry_timer.stop();
|
||||
|
||||
/*
|
||||
if (viewer->seq != nullptr) {
|
||||
gizmos = nullptr;
|
||||
drawn_gizmos = false;
|
||||
@@ -410,53 +506,57 @@ void ViewerWidget::paintGL() {
|
||||
// render the audio
|
||||
QVector<Clip*> nests;
|
||||
compose_sequence(viewer, context(), viewer->seq, nests, false, render_audio, &gizmos);
|
||||
}
|
||||
|
||||
// try to draw the texture from the other thread if we got it
|
||||
if (renderer->mutex.tryLock(10)) {
|
||||
makeCurrent();
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->texColorBuffer);
|
||||
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 1, 1, 0, -1, 1);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glVertex2f(0, 0);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(0, 1);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex2f(1, 1);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex2f(1, 0);
|
||||
glTexCoord2f(0, 1);
|
||||
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
renderer->mutex.unlock();
|
||||
|
||||
if (texture_failed) {
|
||||
qDebug() << "texture failed, retry called";
|
||||
retry_timer.start();
|
||||
}
|
||||
} else {
|
||||
qDebug() << "renderer failed, retry called";
|
||||
retry_timer.start();
|
||||
just_repaint = true;
|
||||
}
|
||||
}
|
||||
// try to draw the texture from the other thread if we got it
|
||||
// if (renderer->mutex.tryLock(10)) {
|
||||
makeCurrent();
|
||||
|
||||
just_repaint = false;
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->texColorBuffer);
|
||||
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 1, 1, 0, -1, 1);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glVertex2f(0, 0);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(0, 1);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex2f(1, 1);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex2f(1, 0);
|
||||
glTexCoord2f(0, 1);
|
||||
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (window != nullptr && window->isVisible()) {
|
||||
window->set_texture(renderer->texColorBuffer, double(viewer->seq->width)/double(viewer->seq->height));
|
||||
}
|
||||
|
||||
// renderer->mutex.unlock();
|
||||
|
||||
// if (texture_failed) {
|
||||
// qDebug() << "texture failed, retry called";
|
||||
// retry_timer.start();
|
||||
// }
|
||||
// } else {
|
||||
// qDebug() << "renderer failed, retry called";
|
||||
// retry_timer.start();
|
||||
// just_repaint = true;
|
||||
// }
|
||||
}
|
||||
|
||||
just_repaint = false;
|
||||
}*/
|
||||
|
||||
|
||||
/*drawn_gizmos = false;
|
||||
|
||||
+8
-7
@@ -19,12 +19,14 @@ class EffectGizmo;
|
||||
class ViewerContainer;
|
||||
struct GLTextureCoords;
|
||||
class RenderThread;
|
||||
class ViewerWindow;
|
||||
|
||||
class ViewerWidget : public QOpenGLWidget, QOpenGLFunctions
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerWidget(QWidget *parent = 0);
|
||||
~ViewerWidget();
|
||||
|
||||
void paintGL();
|
||||
void initializeGL();
|
||||
@@ -40,23 +42,21 @@ public:
|
||||
int waveform_scroll;
|
||||
|
||||
bool force_quit;
|
||||
|
||||
void frame_update();
|
||||
public slots:
|
||||
void delete_function();
|
||||
void set_waveform_scroll(int s);
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e);
|
||||
// void paintEvent(QPaintEvent *e);
|
||||
// void resizeGL(int w, int h);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void mouseReleaseEvent(QMouseEvent *event);
|
||||
private:
|
||||
QTimer retry_timer;
|
||||
void drawTitleSafeArea();
|
||||
bool dragging;
|
||||
void seek_from_click(int x);
|
||||
// GLuint compose_sequence(QVector<Clip *> &nests, bool video, bool render_audio);
|
||||
// GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture, bool clear);
|
||||
// void process_effect(Clip* c, Effect* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, bool& fbo_switcher, int data);
|
||||
Effect* gizmos;
|
||||
int drag_start_x;
|
||||
int drag_start_y;
|
||||
@@ -67,13 +67,14 @@ private:
|
||||
bool drawn_gizmos;
|
||||
void move_gizmos(QMouseEvent *event, bool done);
|
||||
RenderThread* renderer;
|
||||
ViewerWindow* window;
|
||||
bool just_repaint;
|
||||
private slots:
|
||||
void retry();
|
||||
void show_context_menu();
|
||||
void save_frame();
|
||||
void show_fullscreen();
|
||||
|
||||
void queue_repaint();
|
||||
void fullscreen_menu_action(QAction* action);
|
||||
void set_fit_zoom();
|
||||
void set_custom_zoom();
|
||||
void set_menu_zoom(QAction *action);
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "viewerwindow.h"
|
||||
|
||||
ViewerWindow::ViewerWindow(QOpenGLContext *share) :
|
||||
QOpenGLWindow(share),
|
||||
texture(0)
|
||||
{}
|
||||
|
||||
void ViewerWindow::set_texture(GLuint t, double iar) {
|
||||
texture = t;
|
||||
ar = iar;
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewerWindow::paintGL() {
|
||||
if (texture > 0) {
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 1, 1, 0, -1, 1);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
double top = 0;
|
||||
double left = 0;
|
||||
double right = 1;
|
||||
double bottom = 1;
|
||||
|
||||
double widget_ar = double(width()) / double(height());
|
||||
|
||||
if (widget_ar > ar) {
|
||||
/*widget_width = widget_height * aspect_ratio;
|
||||
widget_x = (width() / 2) - (widget_width / 2);*/
|
||||
double width = 1.0 * ar / widget_ar;
|
||||
left = (1.0 - width)*0.5;
|
||||
right = left + width;
|
||||
} else {
|
||||
double height = 1.0 / ar * widget_ar;
|
||||
top = (1.0 - height)*0.5;
|
||||
bottom = top + height;
|
||||
}
|
||||
|
||||
glVertex2d(left, top);
|
||||
glTexCoord2d(0, 0);
|
||||
glVertex2d(left, bottom);
|
||||
glTexCoord2d(1, 0);
|
||||
glVertex2d(right, bottom);
|
||||
glTexCoord2d(1, 1);
|
||||
glVertex2d(right, top);
|
||||
glTexCoord2d(0, 1);
|
||||
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef VIEWERWINDOW_H
|
||||
#define VIEWERWINDOW_H
|
||||
|
||||
#include <QOpenGLWindow>
|
||||
|
||||
class ViewerWindow : public QOpenGLWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerWindow(QOpenGLContext* share);
|
||||
void set_texture(GLuint t, double iar);
|
||||
private:
|
||||
void paintGL();
|
||||
GLuint texture;
|
||||
double ar;
|
||||
};
|
||||
|
||||
#endif // VIEWERWINDOW_H
|
||||
Reference in New Issue
Block a user