various improvements
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
#include "advancedvideodialog.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QComboBox>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
}
|
||||
|
||||
AdvancedVideoDialog::AdvancedVideoDialog(QWidget *parent,
|
||||
int encoding_codec,
|
||||
VideoCodecParams &iparams) :
|
||||
QDialog(parent),
|
||||
params(iparams)
|
||||
{
|
||||
setWindowTitle(tr("Advanced Video Settings"));
|
||||
|
||||
// use variable for row to assist adding new fields to this dialog
|
||||
int row = 0;
|
||||
|
||||
// get encoder information for this codec
|
||||
AVCodec* codec_info = avcodec_find_encoder(static_cast<AVCodecID>(encoding_codec));
|
||||
|
||||
// set up grid layout for dialog
|
||||
QGridLayout* layout = new QGridLayout(this);
|
||||
|
||||
// codec pixel formats
|
||||
layout->addWidget(new QLabel(tr("Pixel Format:")), row, 0);
|
||||
|
||||
pix_fmt_combo = new QComboBox();
|
||||
|
||||
// load possible pixel formats for this codec into the combobox
|
||||
int pix_fmt_index = 0;
|
||||
|
||||
// AVCodec->pix_fmts is terminated by "-1"
|
||||
while (codec_info->pix_fmts[pix_fmt_index] != -1) {
|
||||
pix_fmt_combo->addItem(av_get_pix_fmt_name(codec_info->pix_fmts[pix_fmt_index]),
|
||||
codec_info->pix_fmts[pix_fmt_index]);
|
||||
|
||||
if (codec_info->pix_fmts[pix_fmt_index] == params.pix_fmt) {
|
||||
pix_fmt_combo->setCurrentIndex(pix_fmt_combo->count()-1);
|
||||
}
|
||||
|
||||
pix_fmt_index++;
|
||||
}
|
||||
|
||||
layout->addWidget(pix_fmt_combo, row, 1);
|
||||
|
||||
row++;
|
||||
|
||||
// buttons
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
buttons->setCenterButtons(true);
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
layout->addWidget(buttons, row, 0, 1, 2);
|
||||
}
|
||||
|
||||
void AdvancedVideoDialog::accept() {
|
||||
// store settings back into struct
|
||||
|
||||
params.pix_fmt = pix_fmt_combo->currentData().toInt();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef ADVANCEDVIDEODIALOG_H
|
||||
#define ADVANCEDVIDEODIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "io/exportthread.h"
|
||||
|
||||
class QComboBox;
|
||||
|
||||
class AdvancedVideoDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AdvancedVideoDialog(QWidget* parent,
|
||||
int encoding_codec,
|
||||
VideoCodecParams& iparams);
|
||||
|
||||
void accept();
|
||||
private:
|
||||
VideoCodecParams& params;
|
||||
|
||||
QComboBox* pix_fmt_combo;
|
||||
};
|
||||
|
||||
#endif // ADVANCEDVIDEODIALOG_H
|
||||
+176
-154
@@ -16,6 +16,7 @@
|
||||
#include <QProgressBar>
|
||||
|
||||
#include "debug.h"
|
||||
#include "dialogs/advancedvideodialog.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/timeline.h"
|
||||
@@ -103,10 +104,21 @@ ExportDialog::ExportDialog(QWidget *parent) :
|
||||
ExportDialog::~ExportDialog()
|
||||
{}
|
||||
|
||||
void ExportDialog::format_changed(int index)
|
||||
{
|
||||
format_vcodecs.clear();
|
||||
format_acodecs.clear();
|
||||
void ExportDialog::add_codec_to_combobox(QComboBox* box, enum AVCodecID codec) {
|
||||
QString codec_name;
|
||||
|
||||
AVCodec* codec_info = avcodec_find_encoder(codec);
|
||||
|
||||
if (codec_info == nullptr) {
|
||||
codec_name = tr("Unknown codec name %1").arg(static_cast<int>(codec));
|
||||
} else {
|
||||
codec_name = codec_info->long_name;
|
||||
}
|
||||
|
||||
box->addItem(codec_name, codec);
|
||||
}
|
||||
|
||||
void ExportDialog::format_changed(int index) {
|
||||
vcodecCombobox->clear();
|
||||
acodecCombobox->clear();
|
||||
|
||||
@@ -114,204 +126,186 @@ void ExportDialog::format_changed(int index)
|
||||
int default_acodec = 0;
|
||||
|
||||
switch (index) {
|
||||
case FORMAT_3GPP:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
case FORMAT_3GPP:
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MPEG4);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_H264);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AAC);
|
||||
|
||||
default_vcodec = 1;
|
||||
break;
|
||||
case FORMAT_AIFF:
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_PCM_S16LE);
|
||||
break;
|
||||
case FORMAT_APNG:
|
||||
format_vcodecs.append(AV_CODEC_ID_APNG);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_APNG);
|
||||
break;
|
||||
case FORMAT_AVI:
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_MJPEG);
|
||||
format_vcodecs.append(AV_CODEC_ID_MSVIDEO1);
|
||||
format_vcodecs.append(AV_CODEC_ID_RAWVIDEO);
|
||||
format_vcodecs.append(AV_CODEC_ID_HUFFYUV);
|
||||
format_vcodecs.append(AV_CODEC_ID_DVVIDEO);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_H264);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MPEG4);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MJPEG);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MSVIDEO1);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_RAWVIDEO);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_HUFFYUV);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_DVVIDEO);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_FLAC);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AAC);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_FLAC);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_PCM_S16LE);
|
||||
|
||||
default_vcodec = 3;
|
||||
default_acodec = 5;
|
||||
break;
|
||||
case FORMAT_DNXHD:
|
||||
format_vcodecs.append(AV_CODEC_ID_DNXHD);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_DNXHD);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_PCM_S16LE);
|
||||
break;
|
||||
case FORMAT_AC3:
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_EAC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_EAC3);
|
||||
break;
|
||||
case FORMAT_FLV:
|
||||
format_vcodecs.append(AV_CODEC_ID_FLV1);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_FLV1);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP3);
|
||||
break;
|
||||
case FORMAT_GIF:
|
||||
format_vcodecs.append(AV_CODEC_ID_GIF);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_GIF);
|
||||
break;
|
||||
case FORMAT_IMG:
|
||||
format_vcodecs.append(AV_CODEC_ID_BMP);
|
||||
format_vcodecs.append(AV_CODEC_ID_MJPEG);
|
||||
format_vcodecs.append(AV_CODEC_ID_JPEG2000);
|
||||
format_vcodecs.append(AV_CODEC_ID_PSD);
|
||||
format_vcodecs.append(AV_CODEC_ID_PNG);
|
||||
format_vcodecs.append(AV_CODEC_ID_TIFF);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_BMP);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MJPEG);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_JPEG2000);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_PSD);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_PNG);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_TIFF);
|
||||
|
||||
default_vcodec = 4;
|
||||
break;
|
||||
case FORMAT_MP2:
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP2);
|
||||
break;
|
||||
case FORMAT_MP3:
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP3);
|
||||
break;
|
||||
case FORMAT_MPEG1:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG1VIDEO);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MPEG1VIDEO);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_PCM_S16LE);
|
||||
|
||||
default_acodec = 1;
|
||||
break;
|
||||
case FORMAT_MPEG2:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG2VIDEO);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MPEG2VIDEO);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_PCM_S16LE);
|
||||
|
||||
default_acodec = 1;
|
||||
break;
|
||||
case FORMAT_MPEG4:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MPEG4);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_H264);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AAC);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP3);
|
||||
|
||||
default_vcodec = 1;
|
||||
break;
|
||||
case FORMAT_MPEGTS:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG2VIDEO);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MPEG2VIDEO);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AAC);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP3);
|
||||
|
||||
default_acodec = 2;
|
||||
break;
|
||||
case FORMAT_MKV:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MPEG4);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_H264);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_EAC3);
|
||||
format_acodecs.append(AV_CODEC_ID_FLAC);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_OPUS);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
format_acodecs.append(AV_CODEC_ID_VORBIS);
|
||||
format_acodecs.append(AV_CODEC_ID_WAVPACK);
|
||||
format_acodecs.append(AV_CODEC_ID_WMAV1);
|
||||
format_acodecs.append(AV_CODEC_ID_WMAV2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AAC);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_EAC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_FLAC);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_OPUS);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_PCM_S16LE);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_VORBIS);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_WAVPACK);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_WMAV1);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_WMAV2);
|
||||
|
||||
default_vcodec = 1;
|
||||
break;
|
||||
case FORMAT_OGG:
|
||||
format_vcodecs.append(AV_CODEC_ID_THEORA);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_THEORA);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_OPUS);
|
||||
format_acodecs.append(AV_CODEC_ID_VORBIS);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_OPUS);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_VORBIS);
|
||||
|
||||
default_acodec = 1;
|
||||
break;
|
||||
case FORMAT_MOV:
|
||||
format_vcodecs.append(AV_CODEC_ID_QTRLE);
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
format_vcodecs.append(AV_CODEC_ID_MJPEG);
|
||||
format_vcodecs.append(AV_CODEC_ID_PRORES);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_QTRLE);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MPEG4);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_H264);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_MJPEG);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_PRORES);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AAC);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_AC3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_MP3);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_PCM_S16LE);
|
||||
|
||||
default_vcodec = 2;
|
||||
break;
|
||||
case FORMAT_WAV:
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_PCM_S16LE);
|
||||
break;
|
||||
case FORMAT_WEBM:
|
||||
format_vcodecs.append(AV_CODEC_ID_VP8);
|
||||
format_vcodecs.append(AV_CODEC_ID_VP9);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_VP8);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_VP9);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_OPUS);
|
||||
format_acodecs.append(AV_CODEC_ID_VORBIS);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_OPUS);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_VORBIS);
|
||||
|
||||
default_vcodec = 1;
|
||||
break;
|
||||
case FORMAT_WMV:
|
||||
format_vcodecs.append(AV_CODEC_ID_WMV1);
|
||||
format_vcodecs.append(AV_CODEC_ID_WMV2);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_WMV1);
|
||||
add_codec_to_combobox(vcodecCombobox, AV_CODEC_ID_WMV2);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_WMAV1);
|
||||
format_acodecs.append(AV_CODEC_ID_WMAV2);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_WMAV1);
|
||||
add_codec_to_combobox(acodecCombobox, AV_CODEC_ID_WMAV2);
|
||||
|
||||
default_vcodec = 1;
|
||||
default_acodec = 1;
|
||||
break;
|
||||
default:
|
||||
qCritical() << "Invalid format selection - this is a bug, please inform the developers";
|
||||
}
|
||||
|
||||
AVCodec* codec_info;
|
||||
for (int i=0;i<format_vcodecs.size();i++) {
|
||||
codec_info = avcodec_find_encoder((enum AVCodecID) format_vcodecs.at(i));
|
||||
if (codec_info == nullptr) {
|
||||
vcodecCombobox->addItem("nullptr");
|
||||
} else {
|
||||
vcodecCombobox->addItem(codec_info->long_name);
|
||||
}
|
||||
}
|
||||
for (int i=0;i<format_acodecs.size();i++) {
|
||||
codec_info = avcodec_find_encoder((enum AVCodecID) format_acodecs.at(i));
|
||||
if (codec_info == nullptr) {
|
||||
acodecCombobox->addItem("nullptr");
|
||||
} else {
|
||||
acodecCombobox->addItem(codec_info->long_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vcodecCombobox->setCurrentIndex(default_vcodec);
|
||||
acodecCombobox->setCurrentIndex(default_acodec);
|
||||
|
||||
bool video_enabled = format_vcodecs.size() != 0;
|
||||
bool audio_enabled = format_acodecs.size() != 0;
|
||||
bool video_enabled = vcodecCombobox->count() != 0;
|
||||
bool audio_enabled = acodecCombobox->count() != 0;
|
||||
videoGroupbox->setChecked(video_enabled);
|
||||
audioGroupbox->setChecked(audio_enabled);
|
||||
videoGroupbox->setEnabled(video_enabled);
|
||||
@@ -378,7 +372,7 @@ void ExportDialog::export_action() {
|
||||
ext = "gif";
|
||||
break;
|
||||
case FORMAT_IMG:
|
||||
switch (format_vcodecs.at(vcodecCombobox->currentIndex())) {
|
||||
switch (vcodecCombobox->currentData().toInt()) {
|
||||
case AV_CODEC_ID_BMP:
|
||||
ext = "bmp";
|
||||
break;
|
||||
@@ -498,7 +492,32 @@ void ExportDialog::export_action() {
|
||||
}
|
||||
}
|
||||
|
||||
et = new ExportThread(this);
|
||||
ExportParams params;
|
||||
params.filename = filename;
|
||||
params.video_enabled = videoGroupbox->isChecked();
|
||||
if (params.video_enabled) {
|
||||
params.video_codec = vcodecCombobox->currentData().toInt();
|
||||
params.video_width = widthSpinbox->value();
|
||||
params.video_height = heightSpinbox->value();
|
||||
params.video_frame_rate = framerateSpinbox->value();
|
||||
params.video_compression_type = compressionTypeCombobox->currentData().toInt();
|
||||
params.video_bitrate = videobitrateSpinbox->value();
|
||||
}
|
||||
params.audio_enabled = audioGroupbox->isChecked();
|
||||
if (params.audio_enabled) {
|
||||
params.audio_codec = acodecCombobox->currentData().toInt();
|
||||
params.audio_sampling_rate = samplingRateSpinbox->value();
|
||||
params.audio_bitrate = audiobitrateSpinbox->value();
|
||||
}
|
||||
|
||||
params.start_frame = 0;
|
||||
params.end_frame = sequence->getEndFrame(); // entire sequence
|
||||
if (rangeCombobox->currentIndex() == 1) {
|
||||
params.start_frame = qMax(sequence->workarea_in, params.start_frame);
|
||||
params.end_frame = qMin(sequence->workarea_out, params.end_frame);
|
||||
}
|
||||
|
||||
et = new ExportThread(params, vcodec_params, this);
|
||||
|
||||
connect(et, SIGNAL(finished()), et, SLOT(deleteLater()));
|
||||
connect(et, SIGNAL(finished()), this, SLOT(render_thread_finished()));
|
||||
@@ -510,31 +529,7 @@ void ExportDialog::export_action() {
|
||||
|
||||
mainWindow->autorecover_interval();
|
||||
|
||||
prep_ui_for_render(true);
|
||||
|
||||
et->filename = filename;
|
||||
et->video_enabled = videoGroupbox->isChecked();
|
||||
if (et->video_enabled) {
|
||||
et->video_codec = format_vcodecs.at(vcodecCombobox->currentIndex());
|
||||
et->video_width = widthSpinbox->value();
|
||||
et->video_height = heightSpinbox->value();
|
||||
et->video_frame_rate = framerateSpinbox->value();
|
||||
et->video_compression_type = compressionTypeCombobox->currentData().toInt();
|
||||
et->video_bitrate = videobitrateSpinbox->value();
|
||||
}
|
||||
et->audio_enabled = audioGroupbox->isChecked();
|
||||
if (et->audio_enabled) {
|
||||
et->audio_codec = format_acodecs.at(acodecCombobox->currentIndex());
|
||||
et->audio_sampling_rate = samplingRateSpinbox->value();
|
||||
et->audio_bitrate = audiobitrateSpinbox->value();
|
||||
}
|
||||
|
||||
et->start_frame = 0;
|
||||
et->end_frame = sequence->getEndFrame(); // entire sequence
|
||||
if (rangeCombobox->currentIndex() == 1) {
|
||||
et->start_frame = qMax(sequence->workarea_in, et->start_frame);
|
||||
et->end_frame = qMin(sequence->workarea_out, et->end_frame);
|
||||
}
|
||||
prep_ui_for_render(true);
|
||||
|
||||
et->ed = this;
|
||||
cancelled = false;
|
||||
@@ -561,16 +556,34 @@ void ExportDialog::cancel_render() {
|
||||
|
||||
void ExportDialog::vcodec_changed(int index) {
|
||||
compressionTypeCombobox->clear();
|
||||
if ((format_vcodecs.size() > 0 && format_vcodecs.at(index) == AV_CODEC_ID_H264)) {
|
||||
compressionTypeCombobox->setEnabled(true);
|
||||
compressionTypeCombobox->addItem(tr("Quality-based (Constant Rate Factor)"), COMPRESSION_TYPE_CFR);
|
||||
// compressionTypeCombobox->addItem("File size-based (Two-Pass)", COMPRESSION_TYPE_TARGETSIZE);
|
||||
// compressionTypeCombobox->addItem("Average bitrate (Two-Pass)", COMPRESSION_TYPE_TARGETBR);
|
||||
} else {
|
||||
compressionTypeCombobox->addItem(tr("Constant Bitrate"), COMPRESSION_TYPE_CBR);
|
||||
compressionTypeCombobox->setCurrentIndex(0);
|
||||
compressionTypeCombobox->setEnabled(false);
|
||||
}
|
||||
|
||||
if (vcodecCombobox->count() > 0) {
|
||||
if (vcodecCombobox->itemData(index) == AV_CODEC_ID_H264) {
|
||||
compressionTypeCombobox->setEnabled(true);
|
||||
compressionTypeCombobox->addItem(tr("Quality-based (Constant Rate Factor)"), COMPRESSION_TYPE_CFR);
|
||||
// compressionTypeCombobox->addItem("File size-based (Two-Pass)", COMPRESSION_TYPE_TARGETSIZE);
|
||||
// compressionTypeCombobox->addItem("Average bitrate (Two-Pass)", COMPRESSION_TYPE_TARGETBR);
|
||||
} else {
|
||||
compressionTypeCombobox->addItem(tr("Constant Bitrate"), COMPRESSION_TYPE_CBR);
|
||||
compressionTypeCombobox->setCurrentIndex(0);
|
||||
compressionTypeCombobox->setEnabled(false);
|
||||
}
|
||||
|
||||
// set default pix_fmt for this codec
|
||||
AVCodec* codec_info = avcodec_find_encoder(static_cast<AVCodecID>(vcodecCombobox->itemData(index).toInt()));
|
||||
if (codec_info == nullptr) {
|
||||
QMessageBox::critical(this,
|
||||
tr("Invalid Codec"),
|
||||
tr("Failed to find a suitable encoder for this codec. Export will likely fail."));
|
||||
} else {
|
||||
vcodec_params.pix_fmt = codec_info->pix_fmts[0];
|
||||
if (vcodec_params.pix_fmt == -1) {
|
||||
QMessageBox::critical(this,
|
||||
tr("Invalid Codec"),
|
||||
tr("Failed to find pixel format for this encoder. Export will likely fail."));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExportDialog::comp_type_changed(int) {
|
||||
@@ -593,7 +606,12 @@ void ExportDialog::comp_type_changed(int) {
|
||||
videoBitrateLabel->setText(tr("Target File Size (MB):"));
|
||||
videobitrateSpinbox->setValue(100);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExportDialog::open_advanced_video_dialog() {
|
||||
AdvancedVideoDialog avd(this, vcodecCombobox->currentData().toInt(), vcodec_params);
|
||||
avd.exec();
|
||||
}
|
||||
|
||||
void ExportDialog::setup_ui() {
|
||||
@@ -658,6 +676,10 @@ void ExportDialog::setup_ui() {
|
||||
videobitrateSpinbox->setValue(2);
|
||||
videoGridLayout->addWidget(videobitrateSpinbox, 5, 1, 1, 1);
|
||||
|
||||
QPushButton* advanced_video_button = new QPushButton(tr("Advanced"));
|
||||
connect(advanced_video_button, SIGNAL(clicked(bool)), this, SLOT(open_advanced_video_dialog()));
|
||||
videoGridLayout->addWidget(advanced_video_button, 6, 1);
|
||||
|
||||
verticalLayout->addWidget(videoGroupbox);
|
||||
|
||||
audioGroupbox = new QGroupBox(this);
|
||||
|
||||
@@ -12,6 +12,8 @@ class QLabel;
|
||||
class QProgressBar;
|
||||
class QGroupBox;
|
||||
|
||||
#include "io/exportthread.h"
|
||||
|
||||
class ExportDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -28,17 +30,20 @@ private slots:
|
||||
void render_thread_finished();
|
||||
void vcodec_changed(int index);
|
||||
void comp_type_changed(int index);
|
||||
void open_advanced_video_dialog();
|
||||
|
||||
private:
|
||||
QVector<QString> format_strings;
|
||||
QVector<int> format_vcodecs;
|
||||
QVector<int> format_acodecs;
|
||||
QVector<QString> format_strings;
|
||||
void setup_ui();
|
||||
|
||||
ExportThread* et;
|
||||
void prep_ui_for_render(bool r);
|
||||
bool cancelled;
|
||||
|
||||
void add_codec_to_combobox(QComboBox* box, enum AVCodecID codec);
|
||||
|
||||
VideoCodecParams vcodec_params;
|
||||
|
||||
QComboBox* rangeCombobox;
|
||||
QSpinBox* widthSpinbox;
|
||||
QDoubleSpinBox* videobitrateSpinbox;
|
||||
|
||||
@@ -28,7 +28,7 @@ LoadDialog::LoadDialog(QWidget *parent, bool autorecovery) : QDialog(parent) {
|
||||
cancel_button = new QPushButton(tr("Cancel"), this);
|
||||
connect(cancel_button, SIGNAL(clicked(bool)), this, SLOT(cancel()));
|
||||
|
||||
hboxLayout = new QHBoxLayout(this);
|
||||
hboxLayout = new QHBoxLayout();
|
||||
hboxLayout->addStretch();
|
||||
hboxLayout->addWidget(cancel_button);
|
||||
hboxLayout->addStretch();
|
||||
|
||||
@@ -39,7 +39,7 @@ ReplaceClipMediaDialog::ReplaceClipMediaDialog(QWidget *parent, Media *old_media
|
||||
use_same_media_in_points->setChecked(true);
|
||||
layout->addWidget(use_same_media_in_points);
|
||||
|
||||
QHBoxLayout* buttons = new QHBoxLayout(this);
|
||||
QHBoxLayout* buttons = new QHBoxLayout();
|
||||
|
||||
buttons->addStretch();
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ SpeedDialog::SpeedDialog(QWidget *parent) : QDialog(parent) {
|
||||
|
||||
QVBoxLayout* main_layout = new QVBoxLayout(this);
|
||||
|
||||
QGridLayout* grid = new QGridLayout(this);
|
||||
QGridLayout* grid = new QGridLayout();
|
||||
grid->setSpacing(6);
|
||||
|
||||
grid->addWidget(new QLabel(tr("Speed:"), this), 0, 0);
|
||||
|
||||
+48
-42
@@ -27,7 +27,11 @@ extern "C" {
|
||||
#include <QOpenGLPaintDevice>
|
||||
#include <QPainter>
|
||||
|
||||
ExportThread::ExportThread(QObject *parent) :
|
||||
ExportThread::ExportThread(const ExportParams &iparams,
|
||||
const VideoCodecParams& ivparams,
|
||||
QObject *parent) :
|
||||
params(iparams),
|
||||
vcodec_params(ivparams),
|
||||
QThread(parent),
|
||||
continueEncode(true)
|
||||
{
|
||||
@@ -80,13 +84,13 @@ bool ExportThread::encode(AVFormatContext* ofmt_ctx, AVCodecContext* codec_ctx,
|
||||
|
||||
bool ExportThread::setupVideo() {
|
||||
// if video is disabled, no setup necessary
|
||||
if (!video_enabled) return true;
|
||||
if (!params.video_enabled) return true;
|
||||
|
||||
// find video encoder
|
||||
vcodec = avcodec_find_encoder(static_cast<enum AVCodecID>(video_codec));
|
||||
if (!vcodec) {
|
||||
vcodec = avcodec_find_encoder(static_cast<enum AVCodecID>(params.video_codec));
|
||||
if (!vcodec) {
|
||||
qCritical() << "Could not find video encoder";
|
||||
ed->export_error = tr("could not video encoder for %1").arg(QString::number(video_codec));
|
||||
ed->export_error = tr("could not video encoder for %1").arg(QString::number(params.video_codec));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -109,14 +113,16 @@ bool ExportThread::setupVideo() {
|
||||
}
|
||||
|
||||
// setup context
|
||||
vcodec_ctx->codec_id = static_cast<enum AVCodecID>(video_codec);
|
||||
vcodec_ctx->codec_id = static_cast<enum AVCodecID>(params.video_codec);
|
||||
vcodec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
vcodec_ctx->width = video_width;
|
||||
vcodec_ctx->height = video_height;
|
||||
vcodec_ctx->width = params.video_width;
|
||||
vcodec_ctx->height = params.video_height;
|
||||
vcodec_ctx->sample_aspect_ratio = {1, 1};
|
||||
vcodec_ctx->pix_fmt = vcodec->pix_fmts[0]; // maybe be breakable code
|
||||
vcodec_ctx->framerate = av_d2q(video_frame_rate, INT_MAX);
|
||||
if (video_compression_type == COMPRESSION_TYPE_CBR) vcodec_ctx->bit_rate = qRound(video_bitrate * 1000000);
|
||||
vcodec_ctx->pix_fmt = static_cast<AVPixelFormat>(vcodec_params.pix_fmt);
|
||||
vcodec_ctx->framerate = av_d2q(params.video_frame_rate, INT_MAX);
|
||||
if (params.video_compression_type == COMPRESSION_TYPE_CBR) {
|
||||
vcodec_ctx->bit_rate = qRound(params.video_bitrate * 1000000);
|
||||
}
|
||||
vcodec_ctx->time_base = av_inv_q(vcodec_ctx->framerate);
|
||||
video_stream->time_base = vcodec_ctx->time_base;
|
||||
|
||||
@@ -126,9 +132,9 @@ bool ExportThread::setupVideo() {
|
||||
|
||||
switch (vcodec_ctx->codec_id) {
|
||||
case AV_CODEC_ID_H264:
|
||||
switch (video_compression_type) {
|
||||
switch (params.video_compression_type) {
|
||||
case COMPRESSION_TYPE_CFR:
|
||||
av_opt_set(vcodec_ctx->priv_data, "crf", QString::number(static_cast<int>(video_bitrate)).toUtf8(), AV_OPT_SEARCH_CHILDREN);
|
||||
av_opt_set(vcodec_ctx->priv_data, "crf", QString::number(static_cast<int>(params.video_bitrate)).toUtf8(), AV_OPT_SEARCH_CHILDREN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -166,8 +172,8 @@ bool ExportThread::setupVideo() {
|
||||
sequence->width,
|
||||
sequence->height,
|
||||
AV_PIX_FMT_RGBA,
|
||||
video_width,
|
||||
video_height,
|
||||
params.video_width,
|
||||
params.video_height,
|
||||
vcodec_ctx->pix_fmt,
|
||||
SWS_FAST_BILINEAR,
|
||||
nullptr,
|
||||
@@ -180,13 +186,13 @@ bool ExportThread::setupVideo() {
|
||||
|
||||
bool ExportThread::setupAudio() {
|
||||
// if audio is disabled, no setup necessary
|
||||
if (!audio_enabled) return true;
|
||||
if (!params.audio_enabled) return true;
|
||||
|
||||
// find encoder
|
||||
acodec = avcodec_find_encoder(static_cast<AVCodecID>(audio_codec));
|
||||
acodec = avcodec_find_encoder(static_cast<AVCodecID>(params.audio_codec));
|
||||
if (!acodec) {
|
||||
qCritical() << "Could not find audio encoder";
|
||||
ed->export_error = tr("could not audio encoder for %1").arg(QString::number(audio_codec));
|
||||
ed->export_error = tr("could not audio encoder for %1").arg(QString::number(params.audio_codec));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -209,16 +215,16 @@ bool ExportThread::setupAudio() {
|
||||
}
|
||||
|
||||
// setup context
|
||||
acodec_ctx->codec_id = static_cast<AVCodecID>(audio_codec);
|
||||
acodec_ctx->codec_id = static_cast<AVCodecID>(params.audio_codec);
|
||||
acodec_ctx->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
acodec_ctx->sample_rate = audio_sampling_rate;
|
||||
acodec_ctx->sample_rate = params.audio_sampling_rate;
|
||||
acodec_ctx->channel_layout = AV_CH_LAYOUT_STEREO; // change this to support surround/mono sound in the future (this is what the user sets the output audio to)
|
||||
acodec_ctx->channels = av_get_channel_layout_nb_channels(acodec_ctx->channel_layout);
|
||||
acodec_ctx->sample_fmt = acodec->sample_fmts[0];
|
||||
acodec_ctx->bit_rate = audio_bitrate * 1000;
|
||||
acodec_ctx->bit_rate = params.audio_bitrate * 1000;
|
||||
|
||||
acodec_ctx->time_base.num = 1;
|
||||
acodec_ctx->time_base.den = audio_sampling_rate;
|
||||
acodec_ctx->time_base.den = params.audio_sampling_rate;
|
||||
audio_stream->time_base = acodec_ctx->time_base;
|
||||
|
||||
if (fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
|
||||
@@ -307,18 +313,18 @@ bool ExportThread::setupContainer() {
|
||||
|
||||
void ExportThread::run() {
|
||||
panel_sequence_viewer->pause();
|
||||
panel_sequence_viewer->seek(start_frame);
|
||||
panel_sequence_viewer->seek(params.start_frame);
|
||||
|
||||
// copy filename
|
||||
QByteArray ba = filename.toUtf8();
|
||||
QByteArray ba = params.filename.toUtf8();
|
||||
c_filename = new char[ba.size()+1];
|
||||
strcpy(c_filename, ba.data());
|
||||
|
||||
continueEncode = setupContainer();
|
||||
|
||||
if (video_enabled && continueEncode) continueEncode = setupVideo();
|
||||
if (params.video_enabled && continueEncode) continueEncode = setupVideo();
|
||||
|
||||
if (audio_enabled && continueEncode) continueEncode = setupAudio();
|
||||
if (params.audio_enabled && continueEncode) continueEncode = setupAudio();
|
||||
|
||||
if (continueEncode) {
|
||||
ret = avformat_write_header(fmt_ctx, nullptr);
|
||||
@@ -339,13 +345,13 @@ void ExportThread::run() {
|
||||
|
||||
mutex.lock();
|
||||
|
||||
while (sequence->playhead <= end_frame && continueEncode) {
|
||||
while (sequence->playhead <= params.end_frame && continueEncode) {
|
||||
start_time = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
if (audio_enabled) {
|
||||
if (params.audio_enabled) {
|
||||
compose_audio(nullptr, sequence, true, false);
|
||||
}
|
||||
if (video_enabled) {
|
||||
if (params.video_enabled) {
|
||||
do {
|
||||
// TODO optimize by rendering the next frame while encoding the last
|
||||
renderer->start_render(nullptr, sequence, nullptr, video_frame->data[0], video_frame->linesize[0]/4);
|
||||
@@ -356,8 +362,8 @@ void ExportThread::run() {
|
||||
}
|
||||
|
||||
// encode last frame while rendering next frame
|
||||
double timecode_secs = (double) (sequence->playhead-start_frame) / sequence->frame_rate;
|
||||
if (video_enabled) {
|
||||
double timecode_secs = double(sequence->playhead - params.start_frame) / sequence->frame_rate;
|
||||
if (params.video_enabled) {
|
||||
// create sws_frame for converting pixel format
|
||||
|
||||
//
|
||||
@@ -370,8 +376,8 @@ void ExportThread::run() {
|
||||
|
||||
sws_frame = av_frame_alloc();
|
||||
sws_frame->format = vcodec_ctx->pix_fmt;
|
||||
sws_frame->width = video_width;
|
||||
sws_frame->height = video_height;
|
||||
sws_frame->width = params.video_width;
|
||||
sws_frame->height = params.video_height;
|
||||
av_frame_get_buffer(sws_frame, 0);
|
||||
|
||||
// convert pixel format to format expected by the encoder
|
||||
@@ -383,10 +389,10 @@ void ExportThread::run() {
|
||||
|
||||
av_frame_free(&sws_frame);
|
||||
}
|
||||
if (audio_enabled) {
|
||||
if (params.audio_enabled) {
|
||||
|
||||
// do we need to encode more audio samples?
|
||||
while (continueEncode && file_audio_samples <= (timecode_secs*audio_sampling_rate)) {
|
||||
while (continueEncode && file_audio_samples <= (timecode_secs*params.audio_sampling_rate)) {
|
||||
|
||||
// copy samples from audio buffer to AVFrame
|
||||
int adjusted_read = audio_ibuffer_read%audio_ibuffer_size;
|
||||
@@ -417,11 +423,11 @@ void ExportThread::run() {
|
||||
// generating encoding statistics (time it took to encode this frame/estimated remaining time)
|
||||
frame_time = (QDateTime::currentMSecsSinceEpoch()-start_time);
|
||||
total_time += frame_time;
|
||||
remaining_frames = (end_frame-sequence->playhead);
|
||||
remaining_frames = (params.end_frame - sequence->playhead);
|
||||
avg_time = (total_time/frame_count);
|
||||
eta = (remaining_frames*avg_time);
|
||||
|
||||
emit progress_changed(qRound((double(sequence->playhead-start_frame) / double(end_frame-start_frame)) * 100.0), eta);
|
||||
emit progress_changed(qRound((double(sequence->playhead - params.start_frame) / double(params.end_frame - params.start_frame)) * 100.0), eta);
|
||||
sequence->playhead++;
|
||||
frame_count++;
|
||||
}
|
||||
@@ -432,13 +438,13 @@ void ExportThread::run() {
|
||||
mutex.unlock();
|
||||
|
||||
if (continueEncode) {
|
||||
if (video_enabled) vpkt_alloc = true;
|
||||
if (audio_enabled) apkt_alloc = true;
|
||||
if (params.video_enabled) vpkt_alloc = true;
|
||||
if (params.audio_enabled) apkt_alloc = true;
|
||||
}
|
||||
|
||||
mainWindow->set_rendering_state(false);
|
||||
|
||||
if (audio_enabled && continueEncode) {
|
||||
if (params.audio_enabled && continueEncode) {
|
||||
// flush swresample
|
||||
do {
|
||||
swr_convert_frame(swr_ctx, swr_frame, nullptr);
|
||||
@@ -454,8 +460,8 @@ void ExportThread::run() {
|
||||
if (continueEncode) {
|
||||
// flush remaining packets
|
||||
while (continueVideo && continueAudio) {
|
||||
if (continueVideo && video_enabled) continueVideo = encode(fmt_ctx, vcodec_ctx, nullptr, &video_pkt, video_stream, false);
|
||||
if (continueAudio && audio_enabled) continueAudio = encode(fmt_ctx, acodec_ctx, nullptr, &audio_pkt, audio_stream, true);
|
||||
if (continueVideo && params.video_enabled) continueVideo = encode(fmt_ctx, vcodec_ctx, nullptr, &video_pkt, video_stream, false);
|
||||
if (continueAudio && params.audio_enabled) continueAudio = encode(fmt_ctx, acodec_ctx, nullptr, &audio_pkt, audio_stream, true);
|
||||
}
|
||||
|
||||
ret = av_write_trailer(fmt_ctx);
|
||||
|
||||
+29
-17
@@ -25,28 +25,36 @@ extern "C" {
|
||||
#define COMPRESSION_TYPE_TARGETSIZE 2
|
||||
#define COMPRESSION_TYPE_TARGETBR 3
|
||||
|
||||
// structs that store parameters passed from the export dialogs to this thread
|
||||
|
||||
struct ExportParams {
|
||||
// export parameters
|
||||
QString filename;
|
||||
bool video_enabled;
|
||||
int video_codec;
|
||||
int video_width;
|
||||
int video_height;
|
||||
double video_frame_rate;
|
||||
int video_compression_type;
|
||||
double video_bitrate;
|
||||
bool audio_enabled;
|
||||
int audio_codec;
|
||||
int audio_sampling_rate;
|
||||
int audio_bitrate;
|
||||
long start_frame;
|
||||
long end_frame;
|
||||
};
|
||||
|
||||
struct VideoCodecParams {
|
||||
int pix_fmt;
|
||||
};
|
||||
|
||||
class ExportThread : public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ExportThread(QObject* parent = nullptr);
|
||||
ExportThread(const ExportParams& iparams, const VideoCodecParams& ivparams, QObject* parent = nullptr);
|
||||
void run();
|
||||
|
||||
// export parameters
|
||||
QString filename;
|
||||
bool video_enabled;
|
||||
int video_codec;
|
||||
int video_width;
|
||||
int video_height;
|
||||
double video_frame_rate;
|
||||
int video_compression_type;
|
||||
double video_bitrate;
|
||||
bool audio_enabled;
|
||||
int audio_codec;
|
||||
int audio_sampling_rate;
|
||||
int audio_bitrate;
|
||||
long start_frame;
|
||||
long end_frame;
|
||||
|
||||
QOffscreenSurface surface;
|
||||
|
||||
ExportDialog* ed;
|
||||
@@ -62,6 +70,10 @@ private:
|
||||
bool setupAudio();
|
||||
bool setupContainer();
|
||||
|
||||
// params imported from dialogs
|
||||
ExportParams params;
|
||||
VideoCodecParams vcodec_params;
|
||||
|
||||
AVFormatContext* fmt_ctx;
|
||||
AVStream* video_stream;
|
||||
AVCodec* vcodec;
|
||||
|
||||
@@ -139,7 +139,8 @@ SOURCES += \
|
||||
effects/internal/vsthost.cpp \
|
||||
ui/flowlayout.cpp \
|
||||
dialogs/proxydialog.cpp \
|
||||
io/proxygenerator.cpp
|
||||
io/proxygenerator.cpp \
|
||||
dialogs/advancedvideodialog.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
@@ -242,7 +243,8 @@ HEADERS += \
|
||||
effects/internal/vsthost.h \
|
||||
ui/flowlayout.h \
|
||||
dialogs/proxydialog.h \
|
||||
io/proxygenerator.h
|
||||
io/proxygenerator.h \
|
||||
dialogs/advancedvideodialog.h
|
||||
|
||||
FORMS +=
|
||||
|
||||
|
||||
+73
-7
@@ -10,7 +10,9 @@
|
||||
#include <QApplication>
|
||||
|
||||
LabelSlider::LabelSlider(QWidget* parent) : QLabel(parent) {
|
||||
// set a default frame rate - fallback, shouldn't ever really be used
|
||||
frame_rate = 30;
|
||||
|
||||
decimal_places = 1;
|
||||
drag_start = false;
|
||||
drag_proc = false;
|
||||
@@ -96,7 +98,7 @@ void LabelSlider::set_default_value(double v) {
|
||||
}
|
||||
|
||||
void LabelSlider::set_minimum_value(double v) {
|
||||
min_value = v;
|
||||
min_value = v;
|
||||
min_enabled = true;
|
||||
}
|
||||
|
||||
@@ -106,47 +108,102 @@ void LabelSlider::set_maximum_value(double v) {
|
||||
}
|
||||
|
||||
void LabelSlider::mousePressEvent(QMouseEvent *ev) {
|
||||
// if primary button is clicked
|
||||
if (ev->button() == Qt::LeftButton) {
|
||||
|
||||
// store initial value to be compared while dragging
|
||||
drag_start_value = internal_value;
|
||||
if (ev->modifiers() & Qt::AltModifier) {
|
||||
|
||||
// alt + click sets labelslider to default value
|
||||
if (ev->modifiers() & Qt::AltModifier) {
|
||||
|
||||
// if the value is not already default, and there is a default to set
|
||||
if (internal_value != default_value && !qIsNaN(default_value)) {
|
||||
|
||||
// cache current value
|
||||
set_previous_value();
|
||||
|
||||
// set back to default
|
||||
set_value(default_value, true);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// if value isn't valid, we set to a "default" of 0
|
||||
if (qIsNaN(internal_value)) internal_value = 0;
|
||||
|
||||
// hide the cursor and store information about it for dragging
|
||||
qApp->setOverrideCursor(Qt::BlankCursor);
|
||||
drag_start = true;
|
||||
drag_start_x = cursor().pos().x();
|
||||
drag_start_y = cursor().pos().y();
|
||||
}
|
||||
|
||||
emit clicked();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// handler if the user clicks with a non-primary button
|
||||
// prevents mouse from getting stuck in "dragging" mode
|
||||
mouseReleaseEvent(ev);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void LabelSlider::mouseMoveEvent(QMouseEvent* event) {
|
||||
if (drag_start) {
|
||||
// if we're dragging
|
||||
|
||||
// we don't actually start fully dragging until the cursor has moved
|
||||
// while the mouse is down, this helps prevent accidental drags
|
||||
drag_proc = true;
|
||||
|
||||
// get amount cursor moved by
|
||||
double diff = (cursor().pos().x()-drag_start_x) + (drag_start_y-cursor().pos().y());
|
||||
|
||||
// ctrl + drag drags in smaller increments
|
||||
if (event->modifiers() & Qt::ControlModifier) diff *= 0.01;
|
||||
|
||||
// we'll also need to drag in smaller increments for a percent value
|
||||
if (display_type == LABELSLIDER_PERCENT) diff *= 0.01;
|
||||
|
||||
// sets the value
|
||||
set_value(internal_value + diff, true);
|
||||
|
||||
// keep the cursor in the same location while dragging
|
||||
cursor().setPos(drag_start_x, drag_start_y);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelSlider::mouseReleaseEvent(QMouseEvent* ev) {
|
||||
void LabelSlider::mouseReleaseEvent(QMouseEvent*) {
|
||||
if (drag_start) {
|
||||
|
||||
// unhide cursor
|
||||
qApp->restoreOverrideCursor();
|
||||
|
||||
drag_start = false;
|
||||
if (drag_proc) {
|
||||
|
||||
if (drag_proc) {
|
||||
// if we just finished fully dragging
|
||||
|
||||
drag_proc = false;
|
||||
|
||||
previous_value = drag_start_value;
|
||||
|
||||
emit valueChanged();
|
||||
|
||||
} else {
|
||||
|
||||
// if the user didn't actually drag, and just clicked in one place,
|
||||
// we instead present a dialog prompt for the user to enter a
|
||||
// specific value
|
||||
|
||||
double d = internal_value;
|
||||
if (display_type == LABELSLIDER_FRAMENUMBER) {
|
||||
|
||||
if (display_type == LABELSLIDER_FRAMENUMBER) {
|
||||
|
||||
// ask the user to enter a timecode
|
||||
QString s = QInputDialog::getText(
|
||||
this,
|
||||
tr("Set Value"),
|
||||
@@ -155,9 +212,16 @@ void LabelSlider::mouseReleaseEvent(QMouseEvent* ev) {
|
||||
valueToString(internal_value)
|
||||
);
|
||||
if (s.isEmpty()) return;
|
||||
d = timecode_to_frame(s, config.timecode_view, frame_rate); // string to frame number
|
||||
|
||||
// parse string timecode to a frame number
|
||||
d = timecode_to_frame(s, config.timecode_view, frame_rate);
|
||||
|
||||
} else {
|
||||
|
||||
// ask the user to enter a normal number value
|
||||
bool ok;
|
||||
|
||||
// percentages are stored 0.0 - 1.0 but displayed as 0% - 100%
|
||||
d = QInputDialog::getDouble(
|
||||
this,
|
||||
tr("Set Value"),
|
||||
@@ -171,6 +235,8 @@ void LabelSlider::mouseReleaseEvent(QMouseEvent* ev) {
|
||||
if (!ok) return;
|
||||
if (display_type == LABELSLIDER_PERCENT) d *= 0.01;
|
||||
}
|
||||
|
||||
// if the value actually changed, trigger a change event
|
||||
if (d != internal_value) {
|
||||
set_previous_value();
|
||||
set_value(d, true);
|
||||
|
||||
Reference in New Issue
Block a user