implemented export dialog functionality and some base formats/codecs to support

This commit is contained in:
itsmattkc
2019-12-16 01:21:30 +11:00
parent d6d8409bb9
commit 3f79845464
13 changed files with 407 additions and 64 deletions
+48
View File
@@ -407,3 +407,51 @@ void Core::SetAutorecoveryInterval(int minutes)
// Convert minutes to milliseconds
autorecovery_timer_.setInterval(minutes * 60000);
}
QList<rational> Core::SupportedFrameRates()
{
QList<rational> frame_rates;
frame_rates.append(rational(10, 1)); // 10 FPS
frame_rates.append(rational(15, 1)); // 15 FPS
frame_rates.append(rational(24000, 1001)); // 23.976 FPS
frame_rates.append(rational(24, 1)); // 24 FPS
frame_rates.append(rational(25, 1)); // 25 FPS
frame_rates.append(rational(30000, 1001)); // 29.97 FPS
frame_rates.append(rational(30, 1)); // 30 FPS
frame_rates.append(rational(48000, 1001)); // 47.952 FPS
frame_rates.append(rational(48, 1)); // 48 FPS
frame_rates.append(rational(50, 1)); // 50 FPS
frame_rates.append(rational(60000, 1001)); // 59.94 FPS
frame_rates.append(rational(60, 1)); // 60 FPS
return frame_rates;
}
QList<int> Core::SupportedSampleRates()
{
QList<int> sample_rates;
sample_rates.append(8000); // 8000 Hz
sample_rates.append(11025); // 11025 Hz
sample_rates.append(16000); // 16000 Hz
sample_rates.append(22050); // 22050 Hz
sample_rates.append(24000); // 24000 Hz
sample_rates.append(32000); // 32000 Hz
sample_rates.append(44100); // 44100 Hz
sample_rates.append(48000); // 48000 Hz
sample_rates.append(88200); // 88200 Hz
sample_rates.append(96000); // 96000 Hz
return sample_rates;
}
QString Core::FrameRateToString(const rational &frame_rate)
{
return tr("%1 FPS").arg(frame_rate.toDouble());
}
QString Core::SampleRateToString(const int &sample_rate)
{
return tr("%1 Hz").arg(sample_rate);
}
+23
View File
@@ -24,6 +24,7 @@
#include <QList>
#include <QTimer>
#include "common/rational.h"
#include "project/project.h"
#include "project/projectviewmodel.h"
#include "window/mainwindow/mainwindow.h"
@@ -127,6 +128,28 @@ public:
*/
void SetAutorecoveryInterval(int minutes);
/**
* @brief Return a list of supported frame rates in rational form
*
* These rationals can be flipped to create a timebase in this frame rate.
*/
static QList<rational> SupportedFrameRates();
/**
* @brief Return a list of supported sample rates in integer form
*/
static QList<int> SupportedSampleRates();
/**
* @brief Convert rational frame rate (i.e. flipped timebase) to a user-friendly string
*/
static QString FrameRateToString(const rational& frame_rate);
/**
* @brief Convert integer sample rate to a user-friendly string
*/
static QString SampleRateToString(const int &sample_rate);
public slots:
/**
* @brief Set the current application-wide tool
+2
View File
@@ -20,6 +20,8 @@ set(OLIVE_SOURCES
dialog/export/export.cpp
dialog/export/exportaudiotab.h
dialog/export/exportaudiotab.cpp
dialog/export/exportcodec.h
dialog/export/exportformat.h
dialog/export/exportvideotab.h
dialog/export/exportvideotab.cpp
PARENT_SCOPE
+157 -9
View File
@@ -1,6 +1,5 @@
#include "export.h"
#include <QComboBox>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QHBoxLayout>
@@ -8,17 +7,18 @@
#include <QPushButton>
#include <QScrollArea>
#include <QSplitter>
#include <QStandardPaths>
#include "exportvideotab.h"
#include "exportaudiotab.h"
#include "ui/icons/icons.h"
ExportDialog::ExportDialog(QWidget *parent) :
QDialog(parent)
QDialog(parent),
previously_selected_format_(0)
{
QHBoxLayout* layout = new QHBoxLayout(this);
QSplitter* splitter = new QSplitter(Qt::Horizontal);
splitter->setChildrenCollapsible(false);
layout->addWidget(splitter);
QWidget* preferences_area = new QWidget();
@@ -29,8 +29,10 @@ ExportDialog::ExportDialog(QWidget *parent) :
QLabel* fn_lbl = new QLabel(tr("Filename:"));
fn_lbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
preferences_layout->addWidget(fn_lbl, row, 0);
filename_edit_ = new QLineEdit();
preferences_layout->addWidget(filename_edit_, row, 1, 1, 2);
QPushButton* file_browse_btn = new QPushButton();
file_browse_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
file_browse_btn->setIcon(olive::icon::Folder);
@@ -43,11 +45,17 @@ ExportDialog::ExportDialog(QWidget *parent) :
QLabel* preset_lbl = new QLabel(tr("Preset:"));
preset_lbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
preferences_layout->addWidget(preset_lbl, row, 0);
preferences_layout->addWidget(new QComboBox(), row, 1);
QComboBox* preset_combobox = new QComboBox();
preset_combobox->addItem(tr("Same As Source - High Quality"));
preset_combobox->addItem(tr("Same As Source - Medium Quality"));
preset_combobox->addItem(tr("Same As Source - Low Quality"));
preferences_layout->addWidget(preset_combobox, row, 1);
QPushButton* preset_load_btn = new QPushButton();
preset_load_btn->setIcon(olive::icon::Open);
preset_load_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
preferences_layout->addWidget(preset_load_btn, row, 2);
QPushButton* preset_save_btn = new QPushButton();
preset_save_btn->setIcon(olive::icon::Save);
preset_save_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
@@ -63,18 +71,22 @@ ExportDialog::ExportDialog(QWidget *parent) :
row++;
preferences_layout->addWidget(new QLabel(tr("Format:")), row, 0);
preferences_layout->addWidget(new QComboBox(), row, 1, 1, 3);
format_combobox_ = new QComboBox();
connect(format_combobox_, SIGNAL(currentIndexChanged(int)), this, SLOT(FormatChanged(int)));
preferences_layout->addWidget(format_combobox_, row, 1, 1, 3);
row++;
QTabWidget* preferences_tabs = new QTabWidget();
QScrollArea* video_area = new QScrollArea();
video_tab_ = new ExportVideoTab();
video_area->setWidgetResizable(true);
video_area->setWidget(new ExportVideoTab());
video_area->setWidget(video_tab_);
preferences_tabs->addTab(video_area, tr("Video"));
QScrollArea* audio_area = new QScrollArea();
audio_tab_ = new ExportAudioTab();
audio_area->setWidgetResizable(true);
audio_area->setWidget(new ExportAudioTab());
audio_area->setWidget(audio_tab_);
preferences_tabs->addTab(audio_area, tr("Audio"));
preferences_layout->addWidget(preferences_tabs, row, 0, 1, 4);
@@ -97,13 +109,149 @@ ExportDialog::ExportDialog(QWidget *parent) :
preview_viewer_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
preview_layout->addWidget(preview_viewer_);
splitter->addWidget(preview_area);
// Set default filename
// FIXME: Use Sequence name and project filename to construct this
SetDefaultFilename();
// Set up available export formats
SetUpFormats();
// Populate combobox formats
foreach (const ExportFormat& format, formats_) {
format_combobox_->addItem(format.name());
}
// Set defaults
format_combobox_->setCurrentIndex(kFormatMPEG4);
}
void ExportDialog::BrowseFilename()
{
QString browsed_fn = QFileDialog::getSaveFileName();
const ExportFormat& current_format = formats_.at(format_combobox_->currentIndex());
QString browsed_fn = QFileDialog::getSaveFileName(this,
"",
filename_edit_->text(),
QStringLiteral("%1 (*.%2)").arg(current_format.name(), current_format.extension()));
if (!browsed_fn.isEmpty()) {
filename_edit_->setText(browsed_fn);
}
}
void ExportDialog::FormatChanged(int index)
{
QString current_filename = filename_edit_->text();
const QString& previously_selected_ext = formats_.at(previously_selected_format_).extension();
const ExportFormat& current_format = formats_.at(index);
const QString& currently_selected_ext = current_format.extension();
// If the previous extension was added, remove it
if (current_filename.endsWith(previously_selected_ext, Qt::CaseInsensitive)) {
current_filename.resize(current_filename.size() - previously_selected_ext.size() - 1);
}
// Add the extension and set it
current_filename.append('.');
current_filename.append(currently_selected_ext);
filename_edit_->setText(current_filename);
previously_selected_format_ = index;
// Update video and audio comboboxes
video_tab_->codec_combobox()->clear();
foreach (int vcodec, current_format.video_codecs()) {
video_tab_->codec_combobox()->addItem(codecs_.at(vcodec).name());
}
audio_tab_->codec_combobox()->clear();
foreach (int acodec, current_format.audio_codecs()) {
audio_tab_->codec_combobox()->addItem(codecs_.at(acodec).name());
}
}
void ExportDialog::SetUpFormats()
{
// Set up codecs
for (int i=0;i<kCodecCount;i++) {
switch (static_cast<Codec>(i)) {
case kCodecDNxHD:
codecs_.append(ExportCodec(tr("DNxHD"), "dnxhd"));
break;
case kCodecH264:
codecs_.append(ExportCodec(tr("H.264"), "libx264"));
break;
case kCodecH265:
codecs_.append(ExportCodec(tr("H.265"), "libx265"));
break;
case kCodecOpenEXR:
codecs_.append(ExportCodec(tr("OpenEXR"), "exr", ExportCodec::kStillImage));
break;
case kCodecPNG:
codecs_.append(ExportCodec(tr("PNG"), "png", ExportCodec::kStillImage));
break;
case kCodecProRes:
codecs_.append(ExportCodec(tr("ProRes"), "prores"));
break;
case kCodecTIFF:
codecs_.append(ExportCodec(tr("TIFF"), "tiff", ExportCodec::kStillImage));
break;
case kCodecMP2:
codecs_.append(ExportCodec(tr("MP2"), "mp2"));
break;
case kCodecMP3:
codecs_.append(ExportCodec(tr("MP3"), "libmp3lame"));
break;
case kCodecAAC:
codecs_.append(ExportCodec(tr("AAC"), "aac"));
break;
case kCodecPCMS16LE:
codecs_.append(ExportCodec(tr("PCM (Signed 16-Bit Little Endian)"), "pcms16le"));
break;
case kCodecCount:
break;
}
}
// Set up formats
for (int i=0;i<kFormatCount;i++) {
switch (static_cast<Format>(i)) {
case kFormatDNxHD:
formats_.append(ExportFormat(tr("DNxHD"), "mxf", {kCodecDNxHD}, {kCodecPCMS16LE}));
break;
case kFormatMatroska:
formats_.append(ExportFormat(tr("Matroska Video"), "mkv", {kCodecH264, kCodecH265}, {kCodecAAC, kCodecMP2, kCodecMP3, kCodecPCMS16LE}));
break;
case kFormatMPEG4:
formats_.append(ExportFormat(tr("MPEG-4 Video"), "mp4", {kCodecH264, kCodecH265}, {kCodecAAC, kCodecMP2, kCodecMP3, kCodecPCMS16LE}));
break;
case kFormatOpenEXR:
formats_.append(ExportFormat(tr("OpenEXR"), "exr", {kCodecOpenEXR}, {}));
break;
case kFormatQuickTime:
formats_.append(ExportFormat(tr("QuickTime"), "mov", {kCodecH264, kCodecH265, kCodecProRes}, {kCodecAAC, kCodecMP2, kCodecMP3, kCodecPCMS16LE}));
break;
case kFormatPNG:
formats_.append(ExportFormat(tr("PNG"), "png", {kCodecPNG}, {}));
break;
case kFormatTIFF:
formats_.append(ExportFormat(tr("TIFF"), "tiff", {kCodecTIFF}, {}));
break;
case kFormatCount:
break;
}
}
}
void ExportDialog::LoadPresets()
{
}
void ExportDialog::SetDefaultFilename()
{
QString doc_location = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QString file_location = QDir(doc_location).filePath("export");
filename_edit_->setText(file_location);
}
+50
View File
@@ -1,9 +1,14 @@
#ifndef EXPORTDIALOG_H
#define EXPORTDIALOG_H
#include <QComboBox>
#include <QDialog>
#include <QLineEdit>
#include "exportaudiotab.h"
#include "exportcodec.h"
#include "exportformat.h"
#include "exportvideotab.h"
#include "widget/viewer/viewer.h"
class ExportDialog : public QDialog
@@ -13,11 +18,56 @@ public:
ExportDialog(QWidget* parent = nullptr);
private:
void SetUpFormats();
void LoadPresets();
void SetDefaultFilename();
QList<ExportFormat> formats_;
int previously_selected_format_;
QList<ExportCodec> codecs_;
ViewerWidget* preview_viewer_;
QLineEdit* filename_edit_;
QComboBox* format_combobox_;
ExportVideoTab* video_tab_;
ExportAudioTab* audio_tab_;
enum Format {
kFormatDNxHD,
kFormatMatroska,
kFormatMPEG4,
kFormatOpenEXR,
kFormatQuickTime,
kFormatPNG,
kFormatTIFF,
kFormatCount
};
enum Codec {
kCodecDNxHD,
kCodecH264,
kCodecH265,
kCodecOpenEXR,
kCodecPNG,
kCodecProRes,
kCodecTIFF,
kCodecMP2,
kCodecMP3,
kCodecAAC,
kCodecPCMS16LE,
kCodecCount
};
private slots:
void BrowseFilename();
void FormatChanged(int index);
};
#endif // EXPORTDIALOG_H
+22 -3
View File
@@ -1,9 +1,10 @@
#include "exportaudiotab.h"
#include <QComboBox>
#include <QGridLayout>
#include <QLabel>
#include "core.h"
ExportAudioTab::ExportAudioTab(QWidget* parent) :
QWidget(parent)
{
@@ -15,12 +16,20 @@ ExportAudioTab::ExportAudioTab(QWidget* parent) :
int row = 0;
layout->addWidget(new QLabel(tr("Codec:")), row, 0);
layout->addWidget(new QComboBox(), row, 1);
codec_combobox_ = new QComboBox();
layout->addWidget(codec_combobox_, row, 1);
row++;
layout->addWidget(new QLabel(tr("Sample Rate:")), row, 0);
layout->addWidget(new QComboBox(), row, 1);
sample_rate_combobox_ = new QComboBox();
QList<int> sample_rates = Core::SupportedSampleRates();
foreach (const int& sr, sample_rates) {
sample_rate_combobox_->addItem(Core::SampleRateToString(sr));
}
layout->addWidget(sample_rate_combobox_, row, 1);
row++;
@@ -34,3 +43,13 @@ ExportAudioTab::ExportAudioTab(QWidget* parent) :
outer_layout->addStretch();
}
QComboBox *ExportAudioTab::codec_combobox() const
{
return codec_combobox_;
}
QComboBox *ExportAudioTab::sample_rate_combobox() const
{
return sample_rate_combobox_;
}
+8
View File
@@ -1,12 +1,20 @@
#ifndef EXPORTAUDIOTAB_H
#define EXPORTAUDIOTAB_H
#include <QComboBox>
#include <QWidget>
class ExportAudioTab : public QWidget
{
public:
ExportAudioTab(QWidget* parent = nullptr);
QComboBox* codec_combobox() const;
QComboBox* sample_rate_combobox() const;
private:
QComboBox* codec_combobox_;
QComboBox* sample_rate_combobox_;
};
#endif // EXPORTAUDIOTAB_H
+31
View File
@@ -0,0 +1,31 @@
#ifndef EXPORTCODEC_H
#define EXPORTCODEC_H
#include <QString>
class ExportCodec {
public:
enum Flag {
kNone,
kStillImage
};
ExportCodec(const QString& name, const QString& id, Flag flags = kNone) :
name_(name),
id_(id),
flags_(flags)
{
}
const QString& name() const {return name_;}
const QString& id() const {return id_;}
const Flag& flags() const {return flags_;}
private:
QString name_;
QString id_;
Flag flags_;
};
#endif // EXPORTCODEC_H
+30
View File
@@ -0,0 +1,30 @@
#ifndef EXPORTFORMAT_H
#define EXPORTFORMAT_H
#include <QList>
#include <QString>
class ExportFormat {
public:
ExportFormat(const QString& name, const QString& extension, const QList<int>& vcodecs, const QList<int>& acodecs) :
name_(name),
extension_(extension),
video_codecs_(vcodecs),
audio_codecs_(acodecs)
{
}
const QString& name() const {return name_;}
const QString& extension() const {return extension_;}
const QList<int>& video_codecs() const {return video_codecs_;}
const QList<int>& audio_codecs() const {return audio_codecs_;}
private:
QString name_;
QString extension_;
QList<int> video_codecs_;
QList<int> audio_codecs_;
};
#endif // EXPORTFORMAT_H
+18 -3
View File
@@ -1,11 +1,12 @@
#include "exportvideotab.h"
#include <QCheckBox>
#include <QComboBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include "core.h"
#include "common/rational.h"
#include "widget/slider/integerslider.h"
ExportVideoTab::ExportVideoTab(QWidget *parent) :
@@ -22,6 +23,11 @@ ExportVideoTab::ExportVideoTab(QWidget *parent) :
outer_layout->addStretch();
}
QComboBox *ExportVideoTab::codec_combobox() const
{
return codec_combobox_;
}
QWidget* ExportVideoTab::SetupResolutionSection()
{
int row = 0;
@@ -56,7 +62,14 @@ QWidget* ExportVideoTab::SetupResolutionSection()
row++;
layout->addWidget(new QLabel(tr("Frame Rate:")), row, 0);
layout->addWidget(new QComboBox(), row, 1);
frame_rate_combobox_ = new QComboBox();
QList<rational> frame_rates = Core::SupportedFrameRates();
foreach (const rational& fr, frame_rates) {
frame_rate_combobox_->addItem(Core::FrameRateToString(fr));
}
layout->addWidget(frame_rate_combobox_, row, 1);
return resolution_group;
}
@@ -98,7 +111,9 @@ QWidget *ExportVideoTab::SetupCodecSection()
QGridLayout* codec_layout = new QGridLayout(codec_group);
codec_layout->addWidget(new QLabel(tr("Codec:")), row, 0);
codec_layout->addWidget(new QComboBox(), row, 1);
codec_combobox_ = new QComboBox();
codec_layout->addWidget(codec_combobox_, row, 1);
return codec_group;
}
+6
View File
@@ -1,6 +1,7 @@
#ifndef EXPORTVIDEOTAB_H
#define EXPORTVIDEOTAB_H
#include <QComboBox>
#include <QWidget>
class ExportVideoTab : public QWidget
@@ -8,10 +9,15 @@ class ExportVideoTab : public QWidget
public:
ExportVideoTab(QWidget* parent = nullptr);
QComboBox* codec_combobox() const;
private:
QWidget* SetupResolutionSection();
QWidget* SetupColorSection();
QWidget* SetupCodecSection();
QComboBox* codec_combobox_;
QComboBox* frame_rate_combobox_;
};
#endif // EXPORTVIDEOTAB_H
+10 -37
View File
@@ -27,6 +27,7 @@
#include <QMessageBox>
#include <QVBoxLayout>
#include "core.h"
#include "common/channellayout.h"
#include "common/rational.h"
#include "undo/undostack.h"
@@ -93,7 +94,7 @@ SequenceDialog::SequenceDialog(Sequence* s, Type t, QWidget* parent) :
// Set window title based on type
switch (t) {
case kNew:
setWindowTitle("New Sequence");
setWindowTitle(tr("New Sequence"));
break;
case kExisting:
setWindowTitle(tr("Editing \"%1\"").arg(sequence_->name()));
@@ -101,30 +102,16 @@ SequenceDialog::SequenceDialog(Sequence* s, Type t, QWidget* parent) :
}
// Set up available frame rates
AddFrameRate(rational(10, 1)); // 10 FPS
AddFrameRate(rational(15, 1)); // 15 FPS
AddFrameRate(rational(24000, 1001)); // 23.976 FPS
AddFrameRate(rational(24, 1)); // 24 FPS
AddFrameRate(rational(25, 1)); // 25 FPS
AddFrameRate(rational(30000, 1001)); // 29.97 FPS
AddFrameRate(rational(30, 1)); // 30 FPS
AddFrameRate(rational(48000, 1001)); // 47.952 FPS
AddFrameRate(rational(48, 1)); // 48 FPS
AddFrameRate(rational(50, 1)); // 50 FPS
AddFrameRate(rational(60000, 1001)); // 59.94 FPS
AddFrameRate(rational(60, 1)); // 60 FPS
frame_rate_list_ = Core::SupportedFrameRates();
foreach (const rational& fr, frame_rate_list_) {
video_frame_rate_field_->addItem(Core::FrameRateToString(fr));
}
// Set up available sample rates
AddSampleRate(8000); // 8000 Hz
AddSampleRate(11025); // 11025 Hz
AddSampleRate(16000); // 16000 Hz
AddSampleRate(22050); // 22050 Hz
AddSampleRate(24000); // 24000 Hz
AddSampleRate(32000); // 32000 Hz
AddSampleRate(44100); // 44100 Hz
AddSampleRate(48000); // 48000 Hz
AddSampleRate(88200); // 88200 Hz
AddSampleRate(96000); // 96000 Hz
sample_rate_list_ = Core::SupportedSampleRates();
foreach (const int& sr, sample_rate_list_) {
audio_sample_rate_field_->addItem(Core::SampleRateToString(sr));
}
// Set up available channel layouts
AddChannelLayout(AV_CH_LAYOUT_MONO);
@@ -202,20 +189,6 @@ void SequenceDialog::accept()
QDialog::accept();
}
void SequenceDialog::AddFrameRate(const rational &r)
{
frame_rate_list_.append(r);
video_frame_rate_field_->addItem(tr("%1 FPS").arg(r.toDouble()));
}
void SequenceDialog::AddSampleRate(const int &rate)
{
sample_rate_list_.append(rate);
audio_sample_rate_field_->addItem(tr("%1 Hz").arg(rate));
}
void SequenceDialog::AddChannelLayout(int layout)
{
QString layout_name;
+2 -12
View File
@@ -82,16 +82,6 @@ public slots:
virtual void accept() override;
private:
/**
* @brief Internal function for adding a selectable frame rate
*/
void AddFrameRate(const rational& r);
/**
* @brief Internal function for adding a selectable sample rate
*/
void AddSampleRate(const int &rate);
/**
* @brief Internal function for adding a selectable channel layout
*/
@@ -113,9 +103,9 @@ private:
QLineEdit* name_field_;
QVector<rational> frame_rate_list_;
QList<rational> frame_rate_list_;
QVector<int> sample_rate_list_;
QList<int> sample_rate_list_;
/**
* @brief A QUndoCommand for setting the parameters on a sequence