diff --git a/dialogs/exportdialog.cpp b/dialogs/exportdialog.cpp index 98c4089b2..ec7a0ab7f 100644 --- a/dialogs/exportdialog.cpp +++ b/dialogs/exportdialog.cpp @@ -599,17 +599,16 @@ void ExportDialog::comp_type_changed(int) { void ExportDialog::setup_ui() { QVBoxLayout* verticalLayout = new QVBoxLayout(this); - QHBoxLayout* format_layout = new QHBoxLayout(this); + QHBoxLayout* format_layout = new QHBoxLayout(); format_layout->addWidget(new QLabel(tr("Format:"), this)); - formatCombobox = new QComboBox(this); - + formatCombobox = new QComboBox(); format_layout->addWidget(formatCombobox); verticalLayout->addLayout(format_layout); - QHBoxLayout* range_layout = new QHBoxLayout(this); + QHBoxLayout* range_layout = new QHBoxLayout(); range_layout->addWidget(new QLabel(tr("Range:"), this)); @@ -685,7 +684,7 @@ void ExportDialog::setup_ui() { verticalLayout->addWidget(audioGroupbox); - QHBoxLayout* progressLayout = new QHBoxLayout(this); + QHBoxLayout* progressLayout = new QHBoxLayout(); progressBar = new QProgressBar(this); progressBar->setFormat("%p% (ETA: 0:00:00)"); progressBar->setEnabled(false); @@ -701,7 +700,7 @@ void ExportDialog::setup_ui() { verticalLayout->addLayout(progressLayout); - QHBoxLayout* buttonLayout = new QHBoxLayout(this); + QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->addStretch(); export_button = new QPushButton(this); diff --git a/io/exportthread.cpp b/io/exportthread.cpp index f5eff945a..ad96a4a0b 100644 --- a/io/exportthread.cpp +++ b/io/exportthread.cpp @@ -38,7 +38,6 @@ ExportThread::ExportThread(QObject *parent) : vcodec = nullptr; vcodec_ctx = nullptr; video_frame = nullptr; - sws_frame = nullptr; sws_ctx = nullptr; audio_stream = nullptr; acodec = nullptr; @@ -125,18 +124,17 @@ bool ExportThread::setupVideo() { vcodec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } - if (vcodec_ctx->codec_id == AV_CODEC_ID_H264) { - /*char buffer[50]; - 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 (vcodec_ctx->codec_id) { + case AV_CODEC_ID_H264: switch (video_compression_type) { case COMPRESSION_TYPE_CFR: av_opt_set(vcodec_ctx->priv_data, "crf", QString::number(static_cast(video_bitrate)).toUtf8(), AV_OPT_SEARCH_CHILDREN); break; } + break; + case AV_CODEC_ID_GIF: + av_opt_set(vcodec_ctx->priv_data, "image", "1", AV_OPT_SEARCH_CHILDREN); + break; } AVDictionary* opts = nullptr; @@ -180,12 +178,6 @@ bool ExportThread::setupVideo() { 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; } @@ -369,12 +361,30 @@ void ExportThread::run() { // encode last frame while rendering next frame double timecode_secs = (double) (sequence->playhead-start_frame) / sequence->frame_rate; 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 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)); // send to encoder if (!encode(fmt_ctx, vcodec_ctx, sws_frame, &video_pkt, video_stream, false)) continueEncode = false; + + av_frame_free(&sws_frame); } if (audio_enabled) { // do we need to encode more audio samples? @@ -481,7 +491,6 @@ void ExportThread::run() { if (sws_ctx != nullptr) { sws_freeContext(sws_ctx); - av_frame_free(&sws_frame); } if (swr_ctx != nullptr) { swr_free(&swr_ctx); diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index e815a2873..ca2fd3bbe 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -19,6 +19,7 @@ #include #define WAVEFORM_RESOLUTION 64 +#define THUMBNAIL_RESOLUTION 120 extern "C" { #include @@ -30,7 +31,7 @@ extern "C" { QSemaphore sem(5); // only 5 preview generators can run at one time PreviewGenerator::PreviewGenerator(Media* i, Footage* m, bool r) : - QThread(0), + QThread(nullptr), fmt_ctx(nullptr), media(i), footage(m), @@ -50,7 +51,7 @@ PreviewGenerator::PreviewGenerator(Media* i, Footage* m, bool r) : void PreviewGenerator::parse_media() { // detect video/audio streams in file - for (int i=0;i<(int)fmt_ctx->nb_streams;i++) { + for (int i=0;inb_streams);i++) { // Find the decoder for the video stream if (avcodec_find_decoder(fmt_ctx->streams[i]->codecpar->codec_id) == nullptr) { qCritical() << "Unsupported codec in stream" << i << "of file" << footage->name; @@ -106,7 +107,7 @@ void PreviewGenerator::parse_media() { append = true; } else if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { 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; append = true; @@ -277,9 +278,9 @@ void PreviewGenerator::generate_waveform() { if (s != nullptr) { if (fmt_ctx->streams[packet->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (!s->preview_done) { - int dstH = 120; - int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height); - uint8_t* data = new uint8_t[dstW*dstH*4]; + int dstH = THUMBNAIL_RESOLUTION; + int dstW = qRound(dstH * (float(temp_frame->width)/float(temp_frame->height))); + uint8_t* data = new uint8_t[size_t(dstW*dstH*4)]; sws_ctx = sws_getContext( temp_frame->width, @@ -414,7 +415,7 @@ void PreviewGenerator::generate_waveform() { 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(); } delete [] media_lengths; diff --git a/olive.pro b/olive.pro index 423b5dfac..334fafcb9 100644 --- a/olive.pro +++ b/olive.pro @@ -35,6 +35,10 @@ system("which git") { CONFIG += c++11 +CONFIG(debug, debug|release) { + CONFIG += console +} + SOURCES += \ main.cpp \ mainwindow.cpp \ diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index 935ecd63f..88b13e5bf 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -279,11 +279,11 @@ void EffectControls::setup_ui() { hlayout->setSpacing(0); hlayout->setMargin(0); - QSplitter* splitter = new QSplitter(contents); + QSplitter* splitter = new QSplitter(); splitter->setOrientation(Qt::Horizontal); splitter->setChildrenCollapsible(false); - scrollArea = new QScrollArea(splitter); + scrollArea = new QScrollArea(); scrollArea->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); scrollArea->setFrameShape(QFrame::NoFrame); scrollArea->setFrameShadow(QFrame::Plain); @@ -291,13 +291,13 @@ void EffectControls::setup_ui() { scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); scrollArea->setWidgetResizable(true); - QWidget* scrollAreaWidgetContents = new QWidget(scrollArea); + QWidget* scrollAreaWidgetContents = new QWidget(); QHBoxLayout* scrollAreaLayout = new QHBoxLayout(scrollAreaWidgetContents); scrollAreaLayout->setSpacing(0); scrollAreaLayout->setMargin(0); - effects_area = new EffectsArea(scrollAreaWidgetContents); + effects_area = new EffectsArea(); effects_area->setContextMenuPolicy(Qt::CustomContextMenu); 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->setMargin(0); - vcontainer = new QWidget(effects_area); - QVBoxLayout* vcontainerLayout = new QVBoxLayout(); + vcontainer = new QWidget(); + QVBoxLayout* vcontainerLayout = new QVBoxLayout(vcontainer); vcontainerLayout->setSpacing(0); vcontainerLayout->setMargin(0); - QWidget* veHeader = new QWidget(vcontainer); + QWidget* veHeader = new QWidget(); veHeader->setObjectName(QStringLiteral("veHeader")); veHeader->setStyleSheet(QLatin1String("#veHeader { background: rgba(0, 0, 0, 0.25); }")); @@ -353,11 +353,11 @@ void EffectControls::setup_ui() { effects_area_layout->addWidget(vcontainer); - acontainer = new QWidget(effects_area); + acontainer = new QWidget(); QVBoxLayout* acontainerLayout = new QVBoxLayout(acontainer); acontainerLayout->setSpacing(0); acontainerLayout->setMargin(0); - QWidget* aeHeader = new QWidget(acontainer); + QWidget* aeHeader = new QWidget(); aeHeader->setObjectName(QStringLiteral("aeHeader")); aeHeader->setStyleSheet(QLatin1String("#aeHeader { background: rgba(0, 0, 0, 0.25); }")); @@ -389,7 +389,7 @@ void EffectControls::setup_ui() { acontainerLayout->addWidget(aeHeader); - audio_effect_area = new QWidget(acontainer); + audio_effect_area = new QWidget(); QVBoxLayout* aeAreaLayout = new QVBoxLayout(audio_effect_area); aeAreaLayout->setSpacing(0); aeAreaLayout->setMargin(0); @@ -398,7 +398,7 @@ void EffectControls::setup_ui() { effects_area_layout->addWidget(acontainer); - lblMultipleClipsSelected = new QLabel(effects_area); + lblMultipleClipsSelected = new QLabel(); lblMultipleClipsSelected->setAlignment(Qt::AlignCenter); lblMultipleClipsSelected->setText(tr("(Multiple clips selected)")); effects_area_layout->addWidget(lblMultipleClipsSelected); @@ -409,30 +409,33 @@ void EffectControls::setup_ui() { scrollArea->setWidget(scrollAreaWidgetContents); splitter->addWidget(scrollArea); - QWidget* keyframeArea = new QWidget(splitter); + + QWidget* keyframeArea = new QWidget(); + QSizePolicy keyframe_sp; keyframe_sp.setHorizontalPolicy(QSizePolicy::Minimum); keyframe_sp.setVerticalPolicy(QSizePolicy::Preferred); keyframe_sp.setHorizontalStretch(1); keyframeArea->setSizePolicy(keyframe_sp); + QVBoxLayout* keyframeAreaLayout = new QVBoxLayout(keyframeArea); keyframeAreaLayout->setSpacing(0); keyframeAreaLayout->setMargin(0); - headers = new TimelineHeader(keyframeArea); + headers = new TimelineHeader(); keyframeAreaLayout->addWidget(headers); - QWidget* keyframeCenterWidget = new QWidget(keyframeArea); + QWidget* keyframeCenterWidget = new QWidget(); QHBoxLayout* keyframeCenterLayout = new QHBoxLayout(keyframeCenterWidget); keyframeCenterLayout->setSpacing(0); keyframeCenterLayout->setMargin(0); - keyframeView = new KeyframeView(keyframeCenterWidget); + keyframeView = new KeyframeView(); keyframeCenterLayout->addWidget(keyframeView); - verticalScrollBar = new QScrollBar(keyframeCenterWidget); + verticalScrollBar = new QScrollBar(); verticalScrollBar->setOrientation(Qt::Vertical); keyframeCenterLayout->addWidget(verticalScrollBar); @@ -440,7 +443,7 @@ void EffectControls::setup_ui() { keyframeAreaLayout->addWidget(keyframeCenterWidget); - horizontalScrollBar = new ResizableScrollBar(keyframeArea); + horizontalScrollBar = new ResizableScrollBar(); horizontalScrollBar->setOrientation(Qt::Horizontal); keyframeAreaLayout->addWidget(horizontalScrollBar); diff --git a/panels/panels.cpp b/panels/panels.cpp index bb51363b5..98a61dcd2 100644 --- a/panels/panels.cpp +++ b/panels/panels.cpp @@ -100,6 +100,7 @@ void update_effect_controls() { if (panel_effect_controls->multiple != multiple || !same) { panel_effect_controls->multiple = multiple; + panel_effect_controls->set_clips(selected_clips, mode); } } diff --git a/project/footage.cpp b/project/footage.cpp index c9dbd83f6..c5cdc94e9 100644 --- a/project/footage.cpp +++ b/project/footage.cpp @@ -69,5 +69,6 @@ void FootageStream::make_square_thumb() { int sqx = (diff < 0) ? -diff : 0; int sqy = (diff > 0) ? diff : 0; p.drawImage(sqx, sqy, video_preview); + p.end(); video_preview_square = QIcon(pixmap); } diff --git a/ui/viewercontainer.cpp b/ui/viewercontainer.cpp index 8801db35e..dc02bd520 100644 --- a/ui/viewercontainer.cpp +++ b/ui/viewercontainer.cpp @@ -20,6 +20,9 @@ ViewerContainer::ViewerContainer(QWidget *parent) : horizontal_scrollbar = new QScrollBar(Qt::Horizontal, this); vertical_scrollbar = new QScrollBar(Qt::Vertical, this); + horizontal_scrollbar->setVisible(false); + vertical_scrollbar->setVisible(false); + horizontal_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())); } -ViewerContainer::~ViewerContainer() { - delete child; - - delete horizontal_scrollbar; - delete vertical_scrollbar; -} +ViewerContainer::~ViewerContainer() {} void ViewerContainer::dragScrollPress(const QPoint &p) { drag_start_x = p.x();