export: allow selecting output pixel format
This commit is contained in:
@@ -88,6 +88,11 @@ void EncodingParams::set_video_threads(const int &threads)
|
||||
video_threads_ = threads;
|
||||
}
|
||||
|
||||
void EncodingParams::set_video_pix_fmt(const QString &s)
|
||||
{
|
||||
video_pix_fmt_ = s;
|
||||
}
|
||||
|
||||
const QString &EncodingParams::filename() const
|
||||
{
|
||||
return filename_;
|
||||
@@ -133,6 +138,11 @@ const int &EncodingParams::video_threads() const
|
||||
return video_threads_;
|
||||
}
|
||||
|
||||
const QString &EncodingParams::video_pix_fmt() const
|
||||
{
|
||||
return video_pix_fmt_;
|
||||
}
|
||||
|
||||
bool EncodingParams::audio_enabled() const
|
||||
{
|
||||
return audio_enabled_;
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
void set_video_max_bit_rate(const int64_t& rate);
|
||||
void set_video_buffer_size(const int64_t& sz);
|
||||
void set_video_threads(const int& threads);
|
||||
void set_video_pix_fmt(const QString& s);
|
||||
|
||||
const QString& filename() const;
|
||||
|
||||
@@ -62,6 +63,7 @@ public:
|
||||
const int64_t& video_max_bit_rate() const;
|
||||
const int64_t& video_buffer_size() const;
|
||||
const int& video_threads() const;
|
||||
const QString& video_pix_fmt() const;
|
||||
|
||||
bool audio_enabled() const;
|
||||
const ExportCodec::Codec &audio_codec() const;
|
||||
@@ -83,6 +85,7 @@ private:
|
||||
int64_t video_max_bit_rate_;
|
||||
int64_t video_buffer_size_;
|
||||
int video_threads_;
|
||||
QString video_pix_fmt_;
|
||||
|
||||
bool audio_enabled_;
|
||||
ExportCodec::Codec audio_codec_;
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
|
||||
#include "exportcodec.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
QString ExportCodec::GetCodecName(ExportCodec::Codec c)
|
||||
@@ -77,4 +82,49 @@ bool ExportCodec::IsCodecAStillImage(ExportCodec::Codec c)
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList ExportCodec::GetPixelFormatsForCodec(ExportCodec::Codec c)
|
||||
{
|
||||
QStringList pix_fmts;
|
||||
|
||||
AVCodec* codec_info;
|
||||
|
||||
switch (c) {
|
||||
case kCodecH264:
|
||||
codec_info = avcodec_find_encoder(AV_CODEC_ID_H264);
|
||||
break;
|
||||
case kCodecDNxHD:
|
||||
codec_info = avcodec_find_encoder(AV_CODEC_ID_DNXHD);
|
||||
break;
|
||||
case kCodecProRes:
|
||||
codec_info = avcodec_find_encoder(AV_CODEC_ID_PRORES);
|
||||
break;
|
||||
case kCodecH265:
|
||||
codec_info = avcodec_find_encoder(AV_CODEC_ID_HEVC);
|
||||
break;
|
||||
case kCodecOpenEXR:
|
||||
case kCodecPNG:
|
||||
case kCodecTIFF:
|
||||
// FIXME: Add these in (these will most likely use an OIIOEncoder which doesn't exist yet)
|
||||
codec_info = nullptr;
|
||||
break;
|
||||
case kCodecMP2:
|
||||
case kCodecMP3:
|
||||
case kCodecAAC:
|
||||
case kCodecPCM:
|
||||
case kCodecCount:
|
||||
// These are audio or invalid codecs and therefore have no pixel formats
|
||||
codec_info = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (codec_info) {
|
||||
for (int i=0; codec_info->pix_fmts[i]!=-1; i++) {
|
||||
const char* pix_fmt_name = av_get_pix_fmt_name(codec_info->pix_fmts[i]);
|
||||
pix_fmts.append(pix_fmt_name);
|
||||
}
|
||||
}
|
||||
|
||||
return pix_fmts;
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -51,6 +51,8 @@ public:
|
||||
|
||||
static bool IsCodecAStillImage(Codec c);
|
||||
|
||||
static QStringList GetPixelFormatsForCodec(Codec c);
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
#include "ffmpegencoder.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/pixdesc.h>
|
||||
}
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include "ffmpegcommon.h"
|
||||
@@ -441,9 +445,7 @@ bool FFmpegEncoder::InitializeStream(AVMediaType type, AVStream** stream_ptr, AV
|
||||
codec_ctx->height = params().video_params().height();
|
||||
codec_ctx->sample_aspect_ratio = {1, 1};
|
||||
codec_ctx->time_base = params().video_params().time_base().toAVRational();
|
||||
|
||||
// FIXME: Make this customizable again
|
||||
codec_ctx->pix_fmt = encoder->pix_fmts[0];
|
||||
codec_ctx->pix_fmt = av_get_pix_fmt(params().video_pix_fmt().toUtf8());
|
||||
|
||||
// Set custom options
|
||||
{
|
||||
|
||||
@@ -203,11 +203,6 @@ ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) :
|
||||
this,
|
||||
&ExportDialog::ResolutionChanged);
|
||||
|
||||
connect(video_tab_->codec_combobox(),
|
||||
static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&ExportDialog::VideoCodecChanged);
|
||||
|
||||
connect(video_tab_,
|
||||
&ExportVideoTab::ColorSpaceChanged,
|
||||
preview_viewer_,
|
||||
@@ -232,8 +227,8 @@ void ExportDialog::StartExport()
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate if the entered filename contains the correct extension (the extension is necessary for both FFmpeg and
|
||||
// OIIO to determine the output format)
|
||||
// Validate if the entered filename contains the correct extension (the extension is necessary
|
||||
// for both FFmpeg and OIIO to determine the output format)
|
||||
QString necessary_ext = QStringLiteral(".%1").arg(ExportFormat::GetExtension(static_cast<ExportFormat::Format>(format_combobox_->currentIndex())));
|
||||
|
||||
// If it doesn't, see if the user wants to append it automatically. If not, we don't abort the export.
|
||||
@@ -356,7 +351,6 @@ void ExportDialog::FormatChanged(int index)
|
||||
foreach (ExportCodec::Codec vcodec, ExportFormat::GetVideoCodecs(current_format)) {
|
||||
video_tab_->codec_combobox()->addItem(ExportCodec::GetCodecName(vcodec), vcodec);
|
||||
}
|
||||
VideoCodecChanged();
|
||||
|
||||
audio_tab_->codec_combobox()->clear();
|
||||
foreach (ExportCodec::Codec acodec, ExportFormat::GetAudioCodecs(current_format)) {
|
||||
@@ -396,17 +390,6 @@ void ExportDialog::ResolutionChanged()
|
||||
UpdateViewerDimensions();
|
||||
}
|
||||
|
||||
void ExportDialog::VideoCodecChanged()
|
||||
{
|
||||
ExportCodec::Codec codec = static_cast<ExportCodec::Codec>(video_tab_->codec_combobox()->currentData().toInt());
|
||||
|
||||
if (codec == ExportCodec::kCodecH264) {
|
||||
video_tab_->SetCodecSection(video_tab_->h264_section());
|
||||
} else if (ExportCodec::IsCodecAStillImage(codec)) {
|
||||
video_tab_->SetCodecSection(video_tab_->image_section());
|
||||
}
|
||||
}
|
||||
|
||||
void ExportDialog::LoadPresets()
|
||||
{
|
||||
|
||||
@@ -457,7 +440,7 @@ ExportParams ExportDialog::GenerateParams() const
|
||||
}
|
||||
|
||||
if (video_enabled_->isChecked()) {
|
||||
ExportCodec::Codec video_codec = static_cast<ExportCodec::Codec>(video_tab_->codec_combobox()->currentData().toInt());
|
||||
ExportCodec::Codec video_codec = video_tab_->GetSelectedCodec();
|
||||
params.EnableVideo(video_render_params, video_codec);
|
||||
|
||||
params.set_video_threads(video_tab_->threads());
|
||||
@@ -465,6 +448,8 @@ ExportParams ExportDialog::GenerateParams() const
|
||||
video_tab_->GetCodecSection()->AddOpts(¶ms);
|
||||
|
||||
params.set_color_transform(video_tab_->CurrentOCIOColorSpace());
|
||||
|
||||
params.set_video_pix_fmt(video_tab_->pix_fmt());
|
||||
}
|
||||
|
||||
if (audio_enabled_->isChecked()) {
|
||||
|
||||
@@ -81,8 +81,6 @@ private slots:
|
||||
|
||||
void ResolutionChanged();
|
||||
|
||||
void VideoCodecChanged();
|
||||
|
||||
void UpdateViewerDimensions();
|
||||
|
||||
void StartExport();
|
||||
|
||||
@@ -2,42 +2,61 @@
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
ExportAdvancedVideoDialog::ExportAdvancedVideoDialog(QWidget *parent) :
|
||||
ExportAdvancedVideoDialog::ExportAdvancedVideoDialog(const QList<QString> &pix_fmts, QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("Advanced"));
|
||||
|
||||
QGridLayout* layout = new QGridLayout(this);
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
int row = 0;
|
||||
{
|
||||
// Pixel Settings
|
||||
QGroupBox* pixel_group = new QGroupBox();
|
||||
layout->addWidget(pixel_group);
|
||||
pixel_group->setTitle(tr("Pixel"));
|
||||
|
||||
layout->addWidget(new QLabel(tr("Threads:")), row, 0);
|
||||
QGridLayout* pixel_layout = new QGridLayout(pixel_group);
|
||||
|
||||
thread_slider_ = new IntegerSlider();
|
||||
thread_slider_->SetMinimum(0);
|
||||
thread_slider_->SetDefaultValue(0);
|
||||
layout->addWidget(thread_slider_, row, 1);
|
||||
int row = 0;
|
||||
|
||||
row++;
|
||||
pixel_layout->addWidget(new QLabel(tr("Pixel Format:")), row, 0);
|
||||
|
||||
pixel_format_combobox_ = new QComboBox();
|
||||
pixel_format_combobox_->addItems(pix_fmts);
|
||||
pixel_layout->addWidget(pixel_format_combobox_, row, 1);
|
||||
|
||||
row++;
|
||||
}
|
||||
|
||||
{
|
||||
// Performance Settings
|
||||
QGroupBox* performance_group = new QGroupBox();
|
||||
layout->addWidget(performance_group);
|
||||
performance_group->setTitle(tr("Performance"));
|
||||
|
||||
QGridLayout* performance_layout = new QGridLayout(performance_group);
|
||||
|
||||
int row = 0;
|
||||
|
||||
performance_layout->addWidget(new QLabel(tr("Threads:")), row, 0);
|
||||
|
||||
thread_slider_ = new IntegerSlider();
|
||||
thread_slider_->SetMinimum(0);
|
||||
thread_slider_->SetDefaultValue(0);
|
||||
performance_layout->addWidget(thread_slider_, row, 1);
|
||||
|
||||
row++;
|
||||
}
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttons, &QDialogButtonBox::accepted, this, &ExportAdvancedVideoDialog::accept);
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, &ExportAdvancedVideoDialog::reject);
|
||||
layout->addWidget(buttons, row, 0, 1, 2);
|
||||
}
|
||||
|
||||
int ExportAdvancedVideoDialog::threads() const
|
||||
{
|
||||
return static_cast<int>(thread_slider_->GetValue());
|
||||
}
|
||||
|
||||
void ExportAdvancedVideoDialog::set_threads(int t)
|
||||
{
|
||||
thread_slider_->SetValue(t);
|
||||
layout->addWidget(buttons);
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef EXPORTADVANCEDVIDEODIALOG_H
|
||||
#define EXPORTADVANCEDVIDEODIALOG_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
|
||||
#include "widget/slider/integerslider.h"
|
||||
@@ -11,14 +12,34 @@ class ExportAdvancedVideoDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ExportAdvancedVideoDialog(QWidget* parent = nullptr);
|
||||
ExportAdvancedVideoDialog(const QList<QString>& pix_fmts,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
int threads() const;
|
||||
void set_threads(int t);
|
||||
int threads() const
|
||||
{
|
||||
return static_cast<int>(thread_slider_->GetValue());
|
||||
}
|
||||
|
||||
void set_threads(int t)
|
||||
{
|
||||
thread_slider_->SetValue(t);
|
||||
}
|
||||
|
||||
QString pix_fmt() const
|
||||
{
|
||||
return pixel_format_combobox_->currentText();
|
||||
}
|
||||
|
||||
void set_pix_fmt(const QString& s)
|
||||
{
|
||||
pixel_format_combobox_->setCurrentText(s);
|
||||
}
|
||||
|
||||
private:
|
||||
IntegerSlider* thread_slider_;
|
||||
|
||||
QComboBox* pixel_format_combobox_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -49,6 +49,11 @@ ExportVideoTab::ExportVideoTab(ColorManager* color_manager, QWidget *parent) :
|
||||
outer_layout->addStretch();
|
||||
}
|
||||
|
||||
ExportCodec::Codec ExportVideoTab::GetSelectedCodec() const
|
||||
{
|
||||
return static_cast<ExportCodec::Codec>(codec_combobox()->currentData().toInt());
|
||||
}
|
||||
|
||||
QComboBox *ExportVideoTab::codec_combobox() const
|
||||
{
|
||||
return codec_combobox_;
|
||||
@@ -109,11 +114,6 @@ H264Section *ExportVideoTab::h264_section() const
|
||||
return h264_section_;
|
||||
}
|
||||
|
||||
const int &ExportVideoTab::threads() const
|
||||
{
|
||||
return threads_;
|
||||
}
|
||||
|
||||
QWidget* ExportVideoTab::SetupResolutionSection()
|
||||
{
|
||||
int row = 0;
|
||||
@@ -194,6 +194,10 @@ QWidget *ExportVideoTab::SetupCodecSection()
|
||||
|
||||
codec_combobox_ = new QComboBox();
|
||||
codec_layout->addWidget(codec_combobox_, row, 1);
|
||||
connect(codec_combobox_,
|
||||
static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&ExportVideoTab::VideoCodecChanged);
|
||||
|
||||
row++;
|
||||
|
||||
@@ -222,13 +226,33 @@ void ExportVideoTab::MaintainAspectRatioChanged(bool val)
|
||||
|
||||
void ExportVideoTab::OpenAdvancedDialog()
|
||||
{
|
||||
ExportAdvancedVideoDialog d(this);
|
||||
// Find export formats compatible with this encoder
|
||||
QStringList pixel_formats = ExportCodec::GetPixelFormatsForCodec(GetSelectedCodec());
|
||||
|
||||
ExportAdvancedVideoDialog d(pixel_formats, this);
|
||||
|
||||
d.set_threads(threads_);
|
||||
d.set_pix_fmt(pix_fmt_);
|
||||
|
||||
if (d.exec() == QDialog::Accepted) {
|
||||
threads_ = d.threads();
|
||||
pix_fmt_ = d.pix_fmt();
|
||||
}
|
||||
}
|
||||
|
||||
void ExportVideoTab::VideoCodecChanged()
|
||||
{
|
||||
ExportCodec::Codec codec = GetSelectedCodec();
|
||||
|
||||
if (codec == ExportCodec::kCodecH264) {
|
||||
SetCodecSection(h264_section());
|
||||
} else if (ExportCodec::IsCodecAStillImage(codec)) {
|
||||
SetCodecSection(image_section());
|
||||
}
|
||||
|
||||
// Set default pixel format
|
||||
pix_fmt_ = ExportCodec::GetPixelFormatsForCodec(codec).first();
|
||||
qDebug() << "Set default pix fmt" << pix_fmt_;
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -40,6 +40,8 @@ class ExportVideoTab : public QWidget
|
||||
public:
|
||||
ExportVideoTab(ColorManager* color_manager, QWidget* parent = nullptr);
|
||||
|
||||
ExportCodec::Codec GetSelectedCodec() const;
|
||||
|
||||
QComboBox* codec_combobox() const;
|
||||
|
||||
IntegerSlider* width_slider() const;
|
||||
@@ -57,7 +59,17 @@ public:
|
||||
ImageSection* image_section() const;
|
||||
H264Section* h264_section() const;
|
||||
|
||||
const int& threads() const;
|
||||
const int& threads() const
|
||||
{
|
||||
return threads_;
|
||||
}
|
||||
|
||||
const QString& pix_fmt() const {
|
||||
return pix_fmt_;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void VideoCodecChanged();
|
||||
|
||||
signals:
|
||||
void ColorSpaceChanged(const QString& colorspace);
|
||||
@@ -87,6 +99,8 @@ private:
|
||||
|
||||
int threads_;
|
||||
|
||||
QString pix_fmt_;
|
||||
|
||||
private slots:
|
||||
void MaintainAspectRatioChanged(bool val);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user