Merge remote-tracking branch 'upstream/master' into pull_requests

# Conflicts:
#	io/previewgenerator.cpp
This commit is contained in:
Jonathan Noble
2019-01-21 18:55:44 +00:00
158 changed files with 154905 additions and 567 deletions
+4 -4
View File
@@ -5,15 +5,15 @@ extern "C" {
}
enum QOpenGLTexture::PixelFormat get_gl_pix_fmt_from_av(int format) {
switch (format) {
/*switch (format) {
case AV_PIX_FMT_RGB24: return QOpenGLTexture::RGB;
}
}*/
return QOpenGLTexture::RGBA;
}
enum QOpenGLTexture::TextureFormat get_gl_tex_fmt_from_av(int format) {
switch (format) {
/*switch (format) {
case AV_PIX_FMT_RGB24: return QOpenGLTexture::RGB8_UNorm;
}
}*/
return QOpenGLTexture::RGBA8_UNorm;
}
+2 -2
View File
@@ -3,7 +3,7 @@
#include <QString>
#define SAVE_VERSION 190104 // YYMMDD
#define SAVE_VERSION 190120 // YYMMDD
#define MIN_SAVE_VERSION 190104 // lowest compatible project version
#define TIMECODE_DROP 0
@@ -63,7 +63,7 @@ struct Config {
bool seek_also_selects;
QString css_path;
int effect_textbox_lines;
bool use_software_fallback;
bool use_software_fallback;
void load(QString path);
void save(QString path);
+23
View File
@@ -0,0 +1,23 @@
#include "crossplatformlib.h"
#include <QDebug>
ModulePtr LibLoad(const QString &filename) {
#ifdef _WIN32
LPCWSTR dll_fn_w = reinterpret_cast<const wchar_t*>(filename.utf16());
return LoadLibrary(dll_fn_w);
#elif defined(__linux__) || defined(__APPLE__)
return dlopen(filename.toUtf8(), RTLD_LAZY);
#else
qWarning() << "Olive doesn't know how to open dynamic libraries on this platform, external libraries will not be functional";
return nullptr;
#endif
}
QStringList LibFilter() {
#ifdef _WIN32
return QStringList("*.dll");
#elif defined(__linux__) || defined(__APPLE__)
return {"*.so", "*.dylib"};
#endif
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef CROSSPLATFORMLIB_H
#define CROSSPLATFORMLIB_H
#include <QString>
#ifdef _WIN32
#include <Windows.h>
#define LibAddress GetProcAddress
#define LibClose FreeModule
#define ModulePtr HMODULE
#elif defined(__linux__) || defined(__APPLE__)
#include <dlfcn.h>
#define LibAddress dlsym
#define LibClose dlclose
#define ModulePtr void*
#endif
ModulePtr LibLoad(const QString& filename);
QStringList LibFilter();
#endif // CROSSPLATFORMLIB_H
+2
View File
@@ -489,5 +489,7 @@ void ExportThread::run() {
}
void ExportThread::wake() {
mutex.lock();
waitCond.wakeAll();
mutex.unlock();
}
+46 -18
View File
@@ -18,7 +18,6 @@
#include "debug.h"
#include <QFile>
#include <QMessageBox>
#include <QTreeWidgetItem>
struct TransitionData {
@@ -35,11 +34,21 @@ LoadThread::LoadThread(LoadDialog* l, bool a) : ld(l), autorecovery(a), cancelle
connect(this, SIGNAL(error()), this, SLOT(error_func()));
connect(this, SIGNAL(start_create_dual_transition(const TransitionData*,Clip*,Clip*,const EffectMeta*)), this, SLOT(create_dual_transition(const TransitionData*,Clip*,Clip*,const EffectMeta*)));
connect(this, SIGNAL(start_create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool)), this, SLOT(create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool)));
connect(this, SIGNAL(start_question(const QString&, const QString &, int)), this, SLOT(question_func(const QString &, const QString &, int)));
}
const EffectMeta* get_meta_from_name(const QString& name) {
const EffectMeta* get_meta_from_name(const QString& input) {
int split_index = input.indexOf('/');
QString category;
if (split_index > -1) {
category = input.left(split_index);
}
QString name = input.mid(split_index + 1);
for (int j=0;j<effects.size();j++) {
if (effects.at(j).name == name) {
if (effects.at(j).name == name
&& (effects.at(j).category == category
|| category.isEmpty())) {
return &effects.at(j);
}
}
@@ -152,13 +161,14 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
if (stream.name() == root_search) {
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 (proj_version < MIN_SAVE_VERSION || proj_version > SAVE_VERSION) {
emit start_question(
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
);
waitCond.wait(&mutex);
if (question_btn == QMessageBox::No) {
show_err = false;
return false;
}
@@ -444,11 +454,14 @@ 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) {
emit start_question(
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
);
waitCond.wait(&mutex);
if (question_btn == QMessageBox::No) {
delete s;
return false;
}
@@ -565,10 +578,14 @@ void LoadThread::run() {
cont = !cancelled;
// find project file version
cont = load_worker(file, stream, LOAD_TYPE_VERSION);
if (cont) {
cont = load_worker(file, stream, LOAD_TYPE_VERSION);
}
// find project's internal URL
cont = load_worker(file, stream, LOAD_TYPE_URL);
if (cont) {
cont = load_worker(file, stream, LOAD_TYPE_URL);
}
// load folders first
if (cont) {
@@ -605,7 +622,6 @@ void LoadThread::run() {
xml_error = true;
emit error();
cont = false;
} else {
// attach nested sequence clips to their sequences
for (int i=0;i<loaded_clips.size();i++) {
@@ -626,6 +642,9 @@ void LoadThread::run() {
for (int i=0;i<loaded_media_items.size();i++) {
panel_project->start_preview_generator(loaded_media_items.at(i), true);
}
} else {
error_str = tr("User aborted loading");
emit error();
}
file.close();
@@ -638,6 +657,15 @@ void LoadThread::cancel() {
cancelled = true;
}
void LoadThread::question_func(const QString &title, const QString &text, int buttons) {
question_btn = QMessageBox::warning(
mainWindow,
title,
text,
static_cast<enum QMessageBox::StandardButton>(buttons));
waitCond.wakeAll();
}
void LoadThread::error_func() {
if (xml_error) {
qCritical() << "Error parsing XML." << error_str;
+5
View File
@@ -6,6 +6,7 @@
#include <QXmlStreamReader>
#include <QMutex>
#include <QWaitCondition>
#include <QMessageBox>
class Media;
struct Footage;
@@ -23,12 +24,14 @@ public:
void run();
void cancel();
signals:
void start_question(const QString &title, const QString &text, int buttons);
void success();
void error();
void start_create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const QString *effect_name, const EffectMeta* meta, long effect_length, bool effect_enabled);
void start_create_dual_transition(const TransitionData* td, Clip* primary, Clip* secondary, const EffectMeta* meta);
void report_progress(int p);
private slots:
void question_func(const QString &title, const QString &text, int buttons);
void error_func();
void success_func();
void create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const QString *effect_name, const EffectMeta* meta, long effect_length, bool effect_enabled);
@@ -67,6 +70,8 @@ private:
bool cancelled;
bool xml_error;
QMessageBox::StandardButton question_btn;
};
#endif // LOADTHREAD_H
+9
View File
@@ -32,3 +32,12 @@ QString get_config_path() {
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
}
}
QList<QString> get_effects_paths() {
QList<QString> effects_paths;
effects_paths.append(get_app_dir() + "/effects");
effects_paths.append(get_app_dir() + "/../share/olive-editor/effects");
QString env_path(qgetenv("OLIVE_EFFECTS_PATH"));
if (!env_path.isEmpty()) effects_paths.append(env_path);
return effects_paths;
}
+1
View File
@@ -6,5 +6,6 @@
QString get_app_dir();
QString get_data_path();
QString get_config_path();
QList<QString> get_effects_paths();
#endif // PATH_H
+9 -9
View File
@@ -217,6 +217,10 @@ void PreviewGenerator::finalize_media() {
}
}
void thumb_data_cleanup(void *info) {
delete [] static_cast<uint8_t*>(info);
}
void PreviewGenerator::generate_waveform() {
SwsContext* sws_ctx;
SwrContext* swr_ctx;
@@ -277,7 +281,7 @@ void PreviewGenerator::generate_waveform() {
if (!s->preview_done) {
int dstH = 120;
int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height);
uint8_t* imgData = new uint8_t[dstW*dstH*4];
uint8_t* data = new uint8_t[dstW*dstH*4];
sws_ctx = sws_getContext(
temp_frame->width,
@@ -294,9 +298,9 @@ void PreviewGenerator::generate_waveform() {
int linesize[AV_NUM_DATA_POINTERS];
linesize[0] = dstW*4;
sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &imgData, linesize);
sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize);
s->video_preview = QImage(imgData, dstW, dstH, linesize[0], QImage::Format_RGBA8888);
s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGBA8888, thumb_data_cleanup);
s->make_square_thumb();
// is video interlaced?
@@ -311,8 +315,6 @@ void PreviewGenerator::generate_waveform() {
avcodec_close(codec_ctx[packet->stream_index]);
codec_ctx[packet->stream_index] = nullptr;
}
delete[] imgData;
}
media_lengths[packet->stream_index]++;
} else if (fmt_ctx->streams[packet->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -403,6 +405,7 @@ void PreviewGenerator::generate_waveform() {
for (unsigned int i=0;i<fmt_ctx->nb_streams;i++) {
if (codec_ctx[i] != nullptr) {
avcodec_close(codec_ctx[i]);
avcodec_free_context(&codec_ctx[i]);
}
}
if (retrieve_duration) {
@@ -417,10 +420,7 @@ void PreviewGenerator::generate_waveform() {
finalize_media();
}
delete [] media_lengths;
if (codec_ctx != NULL) {
avcodec_free_context(codec_ctx);
}
delete [] codec_ctx;
}
QString PreviewGenerator::get_thumbnail_path(const QString& hash, const FootageStream& ms) {