code cleanups and fixed gif export #360

This commit is contained in:
itsmattkc
2019-01-30 21:36:07 +11:00
parent 6f3a826da7
commit c19a2dad7d
8 changed files with 67 additions and 51 deletions
+5 -6
View File
@@ -599,17 +599,16 @@ void ExportDialog::comp_type_changed(int) {
void ExportDialog::setup_ui() { void ExportDialog::setup_ui() {
QVBoxLayout* verticalLayout = new QVBoxLayout(this); QVBoxLayout* verticalLayout = new QVBoxLayout(this);
QHBoxLayout* format_layout = new QHBoxLayout(this); QHBoxLayout* format_layout = new QHBoxLayout();
format_layout->addWidget(new QLabel(tr("Format:"), this)); format_layout->addWidget(new QLabel(tr("Format:"), this));
formatCombobox = new QComboBox(this); formatCombobox = new QComboBox();
format_layout->addWidget(formatCombobox); format_layout->addWidget(formatCombobox);
verticalLayout->addLayout(format_layout); verticalLayout->addLayout(format_layout);
QHBoxLayout* range_layout = new QHBoxLayout(this); QHBoxLayout* range_layout = new QHBoxLayout();
range_layout->addWidget(new QLabel(tr("Range:"), this)); range_layout->addWidget(new QLabel(tr("Range:"), this));
@@ -685,7 +684,7 @@ void ExportDialog::setup_ui() {
verticalLayout->addWidget(audioGroupbox); verticalLayout->addWidget(audioGroupbox);
QHBoxLayout* progressLayout = new QHBoxLayout(this); QHBoxLayout* progressLayout = new QHBoxLayout();
progressBar = new QProgressBar(this); progressBar = new QProgressBar(this);
progressBar->setFormat("%p% (ETA: 0:00:00)"); progressBar->setFormat("%p% (ETA: 0:00:00)");
progressBar->setEnabled(false); progressBar->setEnabled(false);
@@ -701,7 +700,7 @@ void ExportDialog::setup_ui() {
verticalLayout->addLayout(progressLayout); verticalLayout->addLayout(progressLayout);
QHBoxLayout* buttonLayout = new QHBoxLayout(this); QHBoxLayout* buttonLayout = new QHBoxLayout();
buttonLayout->addStretch(); buttonLayout->addStretch();
export_button = new QPushButton(this); export_button = new QPushButton(this);
+24 -15
View File
@@ -38,7 +38,6 @@ ExportThread::ExportThread(QObject *parent) :
vcodec = nullptr; vcodec = nullptr;
vcodec_ctx = nullptr; vcodec_ctx = nullptr;
video_frame = nullptr; video_frame = nullptr;
sws_frame = nullptr;
sws_ctx = nullptr; sws_ctx = nullptr;
audio_stream = nullptr; audio_stream = nullptr;
acodec = nullptr; acodec = nullptr;
@@ -125,18 +124,17 @@ bool ExportThread::setupVideo() {
vcodec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; vcodec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
} }
if (vcodec_ctx->codec_id == AV_CODEC_ID_H264) { switch (vcodec_ctx->codec_id) {
/*char buffer[50]; case AV_CODEC_ID_H264:
itoa(vcodec_ctx, buffer, 10);*/
//av_opt_set(vcodec_ctx->priv_data, "preset", "fast", AV_OPT_SEARCH_CHILDREN);
//av_opt_set(vcodec_ctx->priv_data, "x264opts", "opencl", AV_OPT_SEARCH_CHILDREN);
switch (video_compression_type) { switch (video_compression_type) {
case COMPRESSION_TYPE_CFR: 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>(video_bitrate)).toUtf8(), AV_OPT_SEARCH_CHILDREN);
break; break;
} }
break;
case AV_CODEC_ID_GIF:
av_opt_set(vcodec_ctx->priv_data, "image", "1", AV_OPT_SEARCH_CHILDREN);
break;
} }
AVDictionary* opts = nullptr; AVDictionary* opts = nullptr;
@@ -180,12 +178,6 @@ bool ExportThread::setupVideo() {
nullptr nullptr
); );
sws_frame = av_frame_alloc();
sws_frame->format = vcodec_ctx->pix_fmt;
sws_frame->width = video_width;
sws_frame->height = video_height;
av_frame_get_buffer(sws_frame, 0);
return true; return true;
} }
@@ -369,12 +361,30 @@ void ExportThread::run() {
// encode last frame while rendering next frame // encode last frame while rendering next frame
double timecode_secs = (double) (sequence->playhead-start_frame) / sequence->frame_rate; double timecode_secs = (double) (sequence->playhead-start_frame) / sequence->frame_rate;
if (video_enabled) { if (video_enabled) {
// create sws_frame for converting pixel format
//
// - I'm not sure why, but we have to alloc/free sws_frame every frame, or it breaks GIF exporting.
// - (i.e. GIFs get stuck on the first frame)
// - The same problem/solution can be seen here: https://stackoverflow.com/a/38997739
// - Perhaps this is the intended way to use swscale, but it seems inefficient.
// - Anyway, here we are.
//
sws_frame = av_frame_alloc();
sws_frame->format = vcodec_ctx->pix_fmt;
sws_frame->width = video_width;
sws_frame->height = video_height;
av_frame_get_buffer(sws_frame, 0);
// change pixel format // change pixel format
sws_scale(sws_ctx, video_frame->data, video_frame->linesize, 0, video_frame->height, sws_frame->data, sws_frame->linesize); sws_scale(sws_ctx, video_frame->data, video_frame->linesize, 0, video_frame->height, sws_frame->data, sws_frame->linesize);
sws_frame->pts = qRound(timecode_secs/av_q2d(video_stream->time_base)); sws_frame->pts = qRound(timecode_secs/av_q2d(video_stream->time_base));
// send to encoder // send to encoder
if (!encode(fmt_ctx, vcodec_ctx, sws_frame, &video_pkt, video_stream, false)) continueEncode = false; if (!encode(fmt_ctx, vcodec_ctx, sws_frame, &video_pkt, video_stream, false)) continueEncode = false;
av_frame_free(&sws_frame);
} }
if (audio_enabled) { if (audio_enabled) {
// do we need to encode more audio samples? // do we need to encode more audio samples?
@@ -481,7 +491,6 @@ void ExportThread::run() {
if (sws_ctx != nullptr) { if (sws_ctx != nullptr) {
sws_freeContext(sws_ctx); sws_freeContext(sws_ctx);
av_frame_free(&sws_frame);
} }
if (swr_ctx != nullptr) { if (swr_ctx != nullptr) {
swr_free(&swr_ctx); swr_free(&swr_ctx);
+8 -7
View File
@@ -19,6 +19,7 @@
#include <QDateTime> #include <QDateTime>
#define WAVEFORM_RESOLUTION 64 #define WAVEFORM_RESOLUTION 64
#define THUMBNAIL_RESOLUTION 120
extern "C" { extern "C" {
#include <libavformat/avformat.h> #include <libavformat/avformat.h>
@@ -30,7 +31,7 @@ extern "C" {
QSemaphore sem(5); // only 5 preview generators can run at one time QSemaphore sem(5); // only 5 preview generators can run at one time
PreviewGenerator::PreviewGenerator(Media* i, Footage* m, bool r) : PreviewGenerator::PreviewGenerator(Media* i, Footage* m, bool r) :
QThread(0), QThread(nullptr),
fmt_ctx(nullptr), fmt_ctx(nullptr),
media(i), media(i),
footage(m), footage(m),
@@ -50,7 +51,7 @@ PreviewGenerator::PreviewGenerator(Media* i, Footage* m, bool r) :
void PreviewGenerator::parse_media() { void PreviewGenerator::parse_media() {
// detect video/audio streams in file // detect video/audio streams in file
for (int i=0;i<(int)fmt_ctx->nb_streams;i++) { for (int i=0;i<int(fmt_ctx->nb_streams);i++) {
// Find the decoder for the video stream // Find the decoder for the video stream
if (avcodec_find_decoder(fmt_ctx->streams[i]->codecpar->codec_id) == nullptr) { if (avcodec_find_decoder(fmt_ctx->streams[i]->codecpar->codec_id) == nullptr) {
qCritical() << "Unsupported codec in stream" << i << "of file" << footage->name; qCritical() << "Unsupported codec in stream" << i << "of file" << footage->name;
@@ -106,7 +107,7 @@ void PreviewGenerator::parse_media() {
append = true; append = true;
} else if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { } else if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
ms.audio_channels = fmt_ctx->streams[i]->codecpar->channels; ms.audio_channels = fmt_ctx->streams[i]->codecpar->channels;
ms.audio_layout = fmt_ctx->streams[i]->codecpar->channel_layout; ms.audio_layout = int(fmt_ctx->streams[i]->codecpar->channel_layout);
ms.audio_frequency = fmt_ctx->streams[i]->codecpar->sample_rate; ms.audio_frequency = fmt_ctx->streams[i]->codecpar->sample_rate;
append = true; append = true;
@@ -277,9 +278,9 @@ void PreviewGenerator::generate_waveform() {
if (s != nullptr) { if (s != nullptr) {
if (fmt_ctx->streams[packet->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (fmt_ctx->streams[packet->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (!s->preview_done) { if (!s->preview_done) {
int dstH = 120; int dstH = THUMBNAIL_RESOLUTION;
int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height); int dstW = qRound(dstH * (float(temp_frame->width)/float(temp_frame->height)));
uint8_t* data = new uint8_t[dstW*dstH*4]; uint8_t* data = new uint8_t[size_t(dstW*dstH*4)];
sws_ctx = sws_getContext( sws_ctx = sws_getContext(
temp_frame->width, temp_frame->width,
@@ -414,7 +415,7 @@ void PreviewGenerator::generate_waveform() {
maximum_stream = i; maximum_stream = i;
} }
} }
footage->length = (double) media_lengths[maximum_stream] / av_q2d(fmt_ctx->streams[maximum_stream]->avg_frame_rate) * AV_TIME_BASE; // TODO redo with PTS footage->length = double(media_lengths[maximum_stream]) / av_q2d(fmt_ctx->streams[maximum_stream]->avg_frame_rate) * AV_TIME_BASE; // TODO redo with PTS
finalize_media(); finalize_media();
} }
delete [] media_lengths; delete [] media_lengths;
+4
View File
@@ -35,6 +35,10 @@ system("which git") {
CONFIG += c++11 CONFIG += c++11
CONFIG(debug, debug|release) {
CONFIG += console
}
SOURCES += \ SOURCES += \
main.cpp \ main.cpp \
mainwindow.cpp \ mainwindow.cpp \
+20 -17
View File
@@ -279,11 +279,11 @@ void EffectControls::setup_ui() {
hlayout->setSpacing(0); hlayout->setSpacing(0);
hlayout->setMargin(0); hlayout->setMargin(0);
QSplitter* splitter = new QSplitter(contents); QSplitter* splitter = new QSplitter();
splitter->setOrientation(Qt::Horizontal); splitter->setOrientation(Qt::Horizontal);
splitter->setChildrenCollapsible(false); splitter->setChildrenCollapsible(false);
scrollArea = new QScrollArea(splitter); scrollArea = new QScrollArea();
scrollArea->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); scrollArea->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
scrollArea->setFrameShape(QFrame::NoFrame); scrollArea->setFrameShape(QFrame::NoFrame);
scrollArea->setFrameShadow(QFrame::Plain); scrollArea->setFrameShadow(QFrame::Plain);
@@ -291,13 +291,13 @@ void EffectControls::setup_ui() {
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scrollArea->setWidgetResizable(true); scrollArea->setWidgetResizable(true);
QWidget* scrollAreaWidgetContents = new QWidget(scrollArea); QWidget* scrollAreaWidgetContents = new QWidget();
QHBoxLayout* scrollAreaLayout = new QHBoxLayout(scrollAreaWidgetContents); QHBoxLayout* scrollAreaLayout = new QHBoxLayout(scrollAreaWidgetContents);
scrollAreaLayout->setSpacing(0); scrollAreaLayout->setSpacing(0);
scrollAreaLayout->setMargin(0); scrollAreaLayout->setMargin(0);
effects_area = new EffectsArea(scrollAreaWidgetContents); effects_area = new EffectsArea();
effects_area->setContextMenuPolicy(Qt::CustomContextMenu); effects_area->setContextMenuPolicy(Qt::CustomContextMenu);
connect(effects_area, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(effects_area_context_menu())); connect(effects_area, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(effects_area_context_menu()));
@@ -305,12 +305,12 @@ void EffectControls::setup_ui() {
effects_area_layout->setSpacing(0); effects_area_layout->setSpacing(0);
effects_area_layout->setMargin(0); effects_area_layout->setMargin(0);
vcontainer = new QWidget(effects_area); vcontainer = new QWidget();
QVBoxLayout* vcontainerLayout = new QVBoxLayout(); QVBoxLayout* vcontainerLayout = new QVBoxLayout(vcontainer);
vcontainerLayout->setSpacing(0); vcontainerLayout->setSpacing(0);
vcontainerLayout->setMargin(0); vcontainerLayout->setMargin(0);
QWidget* veHeader = new QWidget(vcontainer); QWidget* veHeader = new QWidget();
veHeader->setObjectName(QStringLiteral("veHeader")); veHeader->setObjectName(QStringLiteral("veHeader"));
veHeader->setStyleSheet(QLatin1String("#veHeader { background: rgba(0, 0, 0, 0.25); }")); veHeader->setStyleSheet(QLatin1String("#veHeader { background: rgba(0, 0, 0, 0.25); }"));
@@ -353,11 +353,11 @@ void EffectControls::setup_ui() {
effects_area_layout->addWidget(vcontainer); effects_area_layout->addWidget(vcontainer);
acontainer = new QWidget(effects_area); acontainer = new QWidget();
QVBoxLayout* acontainerLayout = new QVBoxLayout(acontainer); QVBoxLayout* acontainerLayout = new QVBoxLayout(acontainer);
acontainerLayout->setSpacing(0); acontainerLayout->setSpacing(0);
acontainerLayout->setMargin(0); acontainerLayout->setMargin(0);
QWidget* aeHeader = new QWidget(acontainer); QWidget* aeHeader = new QWidget();
aeHeader->setObjectName(QStringLiteral("aeHeader")); aeHeader->setObjectName(QStringLiteral("aeHeader"));
aeHeader->setStyleSheet(QLatin1String("#aeHeader { background: rgba(0, 0, 0, 0.25); }")); aeHeader->setStyleSheet(QLatin1String("#aeHeader { background: rgba(0, 0, 0, 0.25); }"));
@@ -389,7 +389,7 @@ void EffectControls::setup_ui() {
acontainerLayout->addWidget(aeHeader); acontainerLayout->addWidget(aeHeader);
audio_effect_area = new QWidget(acontainer); audio_effect_area = new QWidget();
QVBoxLayout* aeAreaLayout = new QVBoxLayout(audio_effect_area); QVBoxLayout* aeAreaLayout = new QVBoxLayout(audio_effect_area);
aeAreaLayout->setSpacing(0); aeAreaLayout->setSpacing(0);
aeAreaLayout->setMargin(0); aeAreaLayout->setMargin(0);
@@ -398,7 +398,7 @@ void EffectControls::setup_ui() {
effects_area_layout->addWidget(acontainer); effects_area_layout->addWidget(acontainer);
lblMultipleClipsSelected = new QLabel(effects_area); lblMultipleClipsSelected = new QLabel();
lblMultipleClipsSelected->setAlignment(Qt::AlignCenter); lblMultipleClipsSelected->setAlignment(Qt::AlignCenter);
lblMultipleClipsSelected->setText(tr("(Multiple clips selected)")); lblMultipleClipsSelected->setText(tr("(Multiple clips selected)"));
effects_area_layout->addWidget(lblMultipleClipsSelected); effects_area_layout->addWidget(lblMultipleClipsSelected);
@@ -409,30 +409,33 @@ void EffectControls::setup_ui() {
scrollArea->setWidget(scrollAreaWidgetContents); scrollArea->setWidget(scrollAreaWidgetContents);
splitter->addWidget(scrollArea); splitter->addWidget(scrollArea);
QWidget* keyframeArea = new QWidget(splitter);
QWidget* keyframeArea = new QWidget();
QSizePolicy keyframe_sp; QSizePolicy keyframe_sp;
keyframe_sp.setHorizontalPolicy(QSizePolicy::Minimum); keyframe_sp.setHorizontalPolicy(QSizePolicy::Minimum);
keyframe_sp.setVerticalPolicy(QSizePolicy::Preferred); keyframe_sp.setVerticalPolicy(QSizePolicy::Preferred);
keyframe_sp.setHorizontalStretch(1); keyframe_sp.setHorizontalStretch(1);
keyframeArea->setSizePolicy(keyframe_sp); keyframeArea->setSizePolicy(keyframe_sp);
QVBoxLayout* keyframeAreaLayout = new QVBoxLayout(keyframeArea); QVBoxLayout* keyframeAreaLayout = new QVBoxLayout(keyframeArea);
keyframeAreaLayout->setSpacing(0); keyframeAreaLayout->setSpacing(0);
keyframeAreaLayout->setMargin(0); keyframeAreaLayout->setMargin(0);
headers = new TimelineHeader(keyframeArea);
headers = new TimelineHeader();
keyframeAreaLayout->addWidget(headers); keyframeAreaLayout->addWidget(headers);
QWidget* keyframeCenterWidget = new QWidget(keyframeArea); QWidget* keyframeCenterWidget = new QWidget();
QHBoxLayout* keyframeCenterLayout = new QHBoxLayout(keyframeCenterWidget); QHBoxLayout* keyframeCenterLayout = new QHBoxLayout(keyframeCenterWidget);
keyframeCenterLayout->setSpacing(0); keyframeCenterLayout->setSpacing(0);
keyframeCenterLayout->setMargin(0); keyframeCenterLayout->setMargin(0);
keyframeView = new KeyframeView(keyframeCenterWidget); keyframeView = new KeyframeView();
keyframeCenterLayout->addWidget(keyframeView); keyframeCenterLayout->addWidget(keyframeView);
verticalScrollBar = new QScrollBar(keyframeCenterWidget); verticalScrollBar = new QScrollBar();
verticalScrollBar->setOrientation(Qt::Vertical); verticalScrollBar->setOrientation(Qt::Vertical);
keyframeCenterLayout->addWidget(verticalScrollBar); keyframeCenterLayout->addWidget(verticalScrollBar);
@@ -440,7 +443,7 @@ void EffectControls::setup_ui() {
keyframeAreaLayout->addWidget(keyframeCenterWidget); keyframeAreaLayout->addWidget(keyframeCenterWidget);
horizontalScrollBar = new ResizableScrollBar(keyframeArea); horizontalScrollBar = new ResizableScrollBar();
horizontalScrollBar->setOrientation(Qt::Horizontal); horizontalScrollBar->setOrientation(Qt::Horizontal);
keyframeAreaLayout->addWidget(horizontalScrollBar); keyframeAreaLayout->addWidget(horizontalScrollBar);
+1
View File
@@ -100,6 +100,7 @@ void update_effect_controls() {
if (panel_effect_controls->multiple != multiple || !same) { if (panel_effect_controls->multiple != multiple || !same) {
panel_effect_controls->multiple = multiple; panel_effect_controls->multiple = multiple;
panel_effect_controls->set_clips(selected_clips, mode); panel_effect_controls->set_clips(selected_clips, mode);
} }
} }
+1
View File
@@ -69,5 +69,6 @@ void FootageStream::make_square_thumb() {
int sqx = (diff < 0) ? -diff : 0; int sqx = (diff < 0) ? -diff : 0;
int sqy = (diff > 0) ? diff : 0; int sqy = (diff > 0) ? diff : 0;
p.drawImage(sqx, sqy, video_preview); p.drawImage(sqx, sqy, video_preview);
p.end();
video_preview_square = QIcon(pixmap); video_preview_square = QIcon(pixmap);
} }
+4 -6
View File
@@ -20,6 +20,9 @@ ViewerContainer::ViewerContainer(QWidget *parent) :
horizontal_scrollbar = new QScrollBar(Qt::Horizontal, this); horizontal_scrollbar = new QScrollBar(Qt::Horizontal, this);
vertical_scrollbar = new QScrollBar(Qt::Vertical, this); vertical_scrollbar = new QScrollBar(Qt::Vertical, this);
horizontal_scrollbar->setVisible(false);
vertical_scrollbar->setVisible(false);
horizontal_scrollbar->setSingleStep(20); horizontal_scrollbar->setSingleStep(20);
vertical_scrollbar->setSingleStep(20); vertical_scrollbar->setSingleStep(20);
@@ -30,12 +33,7 @@ ViewerContainer::ViewerContainer(QWidget *parent) :
connect(vertical_scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scroll_changed())); connect(vertical_scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scroll_changed()));
} }
ViewerContainer::~ViewerContainer() { ViewerContainer::~ViewerContainer() {}
delete child;
delete horizontal_scrollbar;
delete vertical_scrollbar;
}
void ViewerContainer::dragScrollPress(const QPoint &p) { void ViewerContainer::dragScrollPress(const QPoint &p) {
drag_start_x = p.x(); drag_start_x = p.x();