313 lines
12 KiB
C++
313 lines
12 KiB
C++
#include "export.h"
|
|
|
|
#include <QDialogButtonBox>
|
|
#include <QFileDialog>
|
|
#include <QHBoxLayout>
|
|
#include <QLabel>
|
|
#include <QProgressBar>
|
|
#include <QPushButton>
|
|
#include <QScrollArea>
|
|
#include <QSplitter>
|
|
#include <QStandardPaths>
|
|
|
|
#include "ui/icons/icons.h"
|
|
|
|
ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) :
|
|
QDialog(parent),
|
|
viewer_node_(viewer_node),
|
|
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();
|
|
QGridLayout* preferences_layout = new QGridLayout(preferences_area);
|
|
|
|
int row = 0;
|
|
|
|
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);
|
|
file_browse_btn->setToolTip(tr("Browse for exported file filename"));
|
|
connect(file_browse_btn, SIGNAL(clicked(bool)), this, SLOT(BrowseFilename()));
|
|
preferences_layout->addWidget(file_browse_btn, row, 3);
|
|
|
|
row++;
|
|
|
|
QLabel* preset_lbl = new QLabel(tr("Preset:"));
|
|
preset_lbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
|
preferences_layout->addWidget(preset_lbl, row, 0);
|
|
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);
|
|
preferences_layout->addWidget(preset_save_btn, row, 3);
|
|
|
|
row++;
|
|
|
|
QFrame* horizontal_line = new QFrame();
|
|
horizontal_line->setFrameShape(QFrame::HLine);
|
|
horizontal_line->setFrameShadow(QFrame::Sunken);
|
|
preferences_layout->addWidget(horizontal_line, row, 0, 1, 4);
|
|
|
|
row++;
|
|
|
|
preferences_layout->addWidget(new QLabel(tr("Format:")), row, 0);
|
|
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(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(audio_tab_);
|
|
preferences_tabs->addTab(audio_area, tr("Audio"));
|
|
preferences_layout->addWidget(preferences_tabs, row, 0, 1, 4);
|
|
|
|
row++;
|
|
|
|
QProgressBar* progress_bar = new QProgressBar();
|
|
progress_bar->setEnabled(false);
|
|
progress_bar->setValue(0);
|
|
preferences_layout->addWidget(progress_bar, row, 0, 1, 4);
|
|
|
|
row++;
|
|
|
|
QDialogButtonBox* buttons = new QDialogButtonBox();
|
|
buttons->setCenterButtons(true);
|
|
buttons->addButton(tr("Export"), QDialogButtonBox::AcceptRole);
|
|
buttons->addButton(QDialogButtonBox::Cancel);
|
|
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
|
|
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
|
|
preferences_layout->addWidget(buttons, row, 0, 1, 4);
|
|
|
|
splitter->addWidget(preferences_area);
|
|
|
|
QWidget* preview_area = new QWidget();
|
|
QVBoxLayout* preview_layout = new QVBoxLayout(preview_area);
|
|
preview_layout->addWidget(new QLabel(tr("Preview")));
|
|
preview_viewer_ = new ViewerWidget();
|
|
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);
|
|
video_tab_->width_slider()->SetValue(viewer_node_->video_params().width());
|
|
video_tab_->height_slider()->SetValue(viewer_node_->video_params().height());
|
|
video_tab_->set_frame_rate(viewer_node_->video_params().time_base().flipped());
|
|
audio_tab_->set_sample_rate(viewer_node_->audio_params().sample_rate());
|
|
audio_tab_->set_channel_layout(viewer_node_->audio_params().channel_layout());
|
|
|
|
video_aspect_ratio_ = static_cast<double>(viewer_node_->video_params().width()) / static_cast<double>(viewer_node_->video_params().height());
|
|
|
|
connect(video_tab_->width_slider(), SIGNAL(ValueChanged(int64_t)), this, SLOT(ResolutionChanged()));
|
|
connect(video_tab_->height_slider(), SIGNAL(ValueChanged(int64_t)), this, SLOT(ResolutionChanged()));
|
|
connect(video_tab_->maintain_aspect_checkbox(), SIGNAL(toggled(bool)), this, SLOT(ResolutionChanged()));
|
|
connect(video_tab_->codec_combobox(), SIGNAL(currentIndexChanged(int)), this, SLOT(VideoCodecChanged()));
|
|
connect(video_tab_, SIGNAL(DisplayChanged(const QString&)), preview_viewer_, SLOT(SetOCIODisplay(const QString&)));
|
|
connect(video_tab_, SIGNAL(ViewChanged(const QString&)), preview_viewer_, SLOT(SetOCIOView(const QString&)));
|
|
connect(video_tab_, SIGNAL(LookChanged(const QString&)), preview_viewer_, SLOT(SetOCIOLook(const QString&)));
|
|
|
|
// Set viewer to view the node
|
|
preview_viewer_->ConnectViewerNode(viewer_node_);
|
|
preview_viewer_->SetColorMenuEnabled(false);
|
|
preview_viewer_->SetOCIOParameters(video_tab_->CurrentOCIODisplay(), video_tab_->CurrentOCIOView(), video_tab_->CurrentOCIOLook());
|
|
}
|
|
|
|
void ExportDialog::BrowseFilename()
|
|
{
|
|
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(), vcodec);
|
|
}
|
|
VideoCodecChanged();
|
|
|
|
audio_tab_->codec_combobox()->clear();
|
|
foreach (int acodec, current_format.audio_codecs()) {
|
|
audio_tab_->codec_combobox()->addItem(codecs_.at(acodec).name(), acodec);
|
|
}
|
|
}
|
|
|
|
void ExportDialog::ResolutionChanged()
|
|
{
|
|
if (video_tab_->maintain_aspect_checkbox()->isChecked()) {
|
|
// Keep aspect ratio maintained
|
|
if (sender() == video_tab_->height_slider()) {
|
|
video_tab_->width_slider()->SetValue(qRound(static_cast<double>(video_tab_->height_slider()->GetValue()) * video_aspect_ratio_));
|
|
} else {
|
|
// This catches both the width slider changing and the maintain aspect ratio checkbox changing
|
|
video_tab_->height_slider()->SetValue(qRound(static_cast<double>(video_tab_->width_slider()->GetValue()) / video_aspect_ratio_));
|
|
}
|
|
} else {
|
|
double current_ratio = static_cast<double>(video_tab_->width_slider()->GetValue()) / static_cast<double>(video_tab_->height_slider()->GetValue());
|
|
|
|
// Enable scaling method combobox only if width/height are not equal to sequence size
|
|
video_tab_->scaling_method_combobox()->setEnabled(!qFuzzyCompare(current_ratio, video_aspect_ratio_));
|
|
}
|
|
}
|
|
|
|
void ExportDialog::VideoCodecChanged()
|
|
{
|
|
const ExportCodec& codec = codecs_.at(video_tab_->codec_combobox()->currentData().toInt());
|
|
|
|
video_tab_->show_image_sequence_section(codec.flags() & ExportCodec::kStillImage);
|
|
}
|
|
|
|
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 kCodecPCM:
|
|
codecs_.append(ExportCodec(tr("PCM (Uncompressed)"), "pcm"));
|
|
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}, {kCodecPCM}));
|
|
break;
|
|
case kFormatMatroska:
|
|
formats_.append(ExportFormat(tr("Matroska Video"), "mkv", {kCodecH264, kCodecH265}, {kCodecAAC, kCodecMP2, kCodecMP3, kCodecPCM}));
|
|
break;
|
|
case kFormatMPEG4:
|
|
formats_.append(ExportFormat(tr("MPEG-4 Video"), "mp4", {kCodecH264, kCodecH265}, {kCodecAAC, kCodecMP2, kCodecMP3, kCodecPCM}));
|
|
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, kCodecPCM}));
|
|
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);
|
|
}
|