From 1c7d22a5cd517db88832c1ddcc8a2160dfa6dc93 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 13 Sep 2018 20:17:06 +1000 Subject: [PATCH] added title/action safe areas --- io/config.cpp | 17 +++++++++- io/config.h | 3 ++ io/exportthread.cpp | 13 ++++++-- mainwindow.cpp | 59 ++++++++++++++++++++++++++++++++++- mainwindow.h | 12 +++++++- mainwindow.ui | 54 +++++++++++++++++++++++++++++++- playback/cacher.cpp | 4 +-- ui/viewerwidget.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++- ui/viewerwidget.h | 1 + 9 files changed, 228 insertions(+), 10 deletions(-) diff --git a/io/config.cpp b/io/config.cpp index 504a0d913..2fe567672 100644 --- a/io/config.cpp +++ b/io/config.cpp @@ -18,7 +18,10 @@ Config::Config() paste_seeks(true), rectified_waveforms(false), default_transition_length(30), - timecode_view(TIMECODE_DROP) + timecode_view(TIMECODE_DROP), + show_title_safe_area(false), + use_custom_title_safe_ratio(false), + custom_title_safe_ratio(1) { } @@ -64,6 +67,15 @@ void Config::load(QString path) { } else if (stream.name() == "TimecodeView") { stream.readNext(); timecode_view = stream.text().toInt(); + }else if (stream.name() == "ShowTitleSafeArea") { + stream.readNext(); + show_title_safe_area = (stream.text() == "1"); + } else if (stream.name() == "UseCustomTitleSafeRatio") { + stream.readNext(); + use_custom_title_safe_ratio = (stream.text() == "1"); + } else if (stream.name() == "CustomTitleSafeRatio") { + stream.readNext(); + custom_title_safe_ratio = stream.text().toDouble(); } } } @@ -121,6 +133,9 @@ void Config::save(QString path) { stream.writeTextElement("RectifiedWaveforms", QString::number(rectified_waveforms)); stream.writeTextElement("DefaultTransitionLength", QString::number(default_transition_length)); stream.writeTextElement("TimecodeView", QString::number(timecode_view)); + stream.writeTextElement("ShowTitleSafeArea", QString::number(show_title_safe_area)); + stream.writeTextElement("UseCustomTitleSafeRatio", QString::number(use_custom_title_safe_ratio)); + stream.writeTextElement("CustomTitleSafeRatio", QString::number(custom_title_safe_ratio)); stream.writeEndElement(); stream.writeEndDocument(); // doc diff --git a/io/config.h b/io/config.h index d16542773..906f467fd 100644 --- a/io/config.h +++ b/io/config.h @@ -22,6 +22,9 @@ struct Config { bool rectified_waveforms; int default_transition_length; int timecode_view; + bool show_title_safe_area; + bool use_custom_title_safe_ratio; + double custom_title_safe_ratio; void load(QString path); void save(QString path); diff --git a/io/exportthread.cpp b/io/exportthread.cpp index 332ea5bca..1eb831991 100644 --- a/io/exportthread.cpp +++ b/io/exportthread.cpp @@ -12,7 +12,8 @@ extern "C" { #include - #include + #include + #include #include #include } @@ -108,15 +109,21 @@ bool ExportThread::setupVideo() { vcodec_ctx->sample_aspect_ratio = av_d2q(video_width/video_height, INT_MAX); vcodec_ctx->pix_fmt = vcodec->pix_fmts[0]; // maybe be breakable code vcodec_ctx->framerate = av_d2q(video_frame_rate, INT_MAX); - vcodec_ctx->bit_rate = video_bitrate * 1000000; + vcodec_ctx->bit_rate = video_bitrate * 1000000; vcodec_ctx->time_base = av_inv_q(vcodec_ctx->framerate); if (fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) { vcodec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } + if (vcodec_ctx->codec_id == AV_CODEC_ID_H264) { +// av_opt_set(vcodec_ctx->priv_data, "preset", "veryslow", AV_OPT_SEARCH_CHILDREN); +// av_opt_set(vcodec_ctx->priv_data, "crf", "0", AV_OPT_SEARCH_CHILDREN); + av_opt_set(vcodec_ctx->priv_data, "x264-params", "nal-hrd=cbr", AV_OPT_SEARCH_CHILDREN); + } + // open encoder - vcodec_ctx->gop_size = 12; // ? does this help? + vcodec_ctx->gop_size = 40; // ? does this help? ret = avcodec_open2(vcodec_ctx, vcodec, NULL); if (ret < 0) { qDebug() << "[ERROR] Could not open output video encoder." << ret; diff --git a/mainwindow.cpp b/mainwindow.cpp index 93e5a2ceb..87efd78f3 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -6,6 +6,7 @@ #include "project/sequence.h" #include "ui/sourcetable.h" +#include "ui/viewerwidget.h" #include "panels/panels.h" #include "panels/project.h" @@ -34,6 +35,8 @@ #include #include #include +#include +#include #define OLIVE_FILE_FILTER "Olive Project (*.ove)" @@ -540,8 +543,13 @@ void MainWindow::viewMenu_About_To_Be_Shown() { ui->actionTimeline_Track_Lines->setChecked(config.show_track_lines); ui->actionFrames->setChecked(config.timecode_view == TIMECODE_FRAMES); ui->actionDrop_Frame->setChecked(config.timecode_view == TIMECODE_DROP); -// if (sequence != NULL) ui->actionDrop_Frame->setEnabled(frame_rate_is_droppable(sequence->frame_rate)); ui->actionNon_Drop_Frame->setChecked(config.timecode_view == TIMECODE_NONDROP); + + ui->actionOff->setChecked(!config.show_title_safe_area); + ui->actionDefault->setChecked(config.show_title_safe_area && !config.use_custom_title_safe_ratio); + ui->action4_3->setChecked(config.show_title_safe_area && config.use_custom_title_safe_ratio && config.custom_title_safe_ratio == 4.0/3.0); + ui->action16_9->setChecked(config.show_title_safe_area && config.use_custom_title_safe_ratio && config.custom_title_safe_ratio == 16.0/9.0); + ui->actionCustom->setChecked(config.show_title_safe_area && config.use_custom_title_safe_ratio && !ui->action4_3->isChecked() && !ui->action16_9->isChecked()); } void MainWindow::on_actionFrames_triggered() @@ -715,3 +723,52 @@ void MainWindow::on_actionRectified_Waveforms_triggered() config.rectified_waveforms = !config.rectified_waveforms; panel_timeline->redraw_all_clips(false); } + +void MainWindow::on_actionDefault_triggered() { + config.show_title_safe_area = true; + config.use_custom_title_safe_ratio = false; + panel_viewer->viewer_widget->update(); +} + +void MainWindow::on_actionOff_triggered() { + config.show_title_safe_area = false; + panel_viewer->viewer_widget->update(); +} + +void MainWindow::on_action4_3_triggered() { + config.show_title_safe_area = true; + config.use_custom_title_safe_ratio = true; + config.custom_title_safe_ratio = 4.0/3.0; + panel_viewer->viewer_widget->update(); +} + +void MainWindow::on_action16_9_triggered() { + config.show_title_safe_area = true; + config.use_custom_title_safe_ratio = true; + config.custom_title_safe_ratio = 16.0/9.0; + panel_viewer->viewer_widget->update(); +} + +void MainWindow::on_actionCustom_triggered() { + QString input; + bool invalid = false; + QRegExp arTest("[0-9.]+:[0-9.]+"); + + do { + if (invalid) { + QMessageBox::critical(this, "Invalid aspect ratio", "The aspect ratio '" + input + "' is invalid. Please try again."); + } + + input = QInputDialog::getText(this, "Enter custom aspect ratio", "Enter the aspect ratio to use for the title/action safe area (e.g. 16:9):"); + invalid = !arTest.exactMatch(input) && !input.isEmpty(); + } while (invalid); + + if (!input.isEmpty()) { + QStringList inputList = input.split(':'); + + config.show_title_safe_area = true; + config.use_custom_title_safe_ratio = true; + config.custom_title_safe_ratio = inputList.at(0).toDouble()/inputList.at(1).toDouble(); + panel_viewer->viewer_widget->update(); + } +} diff --git a/mainwindow.h b/mainwindow.h index ea2855f86..7a6e07a4f 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -167,7 +167,17 @@ private slots: void on_actionTimeline_Track_Lines_triggered(); - void on_actionRectified_Waveforms_triggered(); + void on_actionRectified_Waveforms_triggered(); + + void on_actionDefault_triggered(); + + void on_actionOff_triggered(); + + void on_action4_3_triggered(); + + void on_action16_9_triggered(); + + void on_actionCustom_triggered(); private: Ui::MainWindow *ui; diff --git a/mainwindow.ui b/mainwindow.ui index 7fa42b5c3..9b7aa9d64 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -37,7 +37,7 @@ 0 0 653 - 20 + 16 @@ -120,6 +120,16 @@ &View + + + Title/Action Safe Area + + + + + + + @@ -129,6 +139,8 @@ + + @@ -709,6 +721,46 @@ Rectified Waveforms + + + true + + + Default + + + + + true + + + Off + + + + + true + + + 4:3 + + + + + true + + + 16:9 + + + + + true + + + Custom + + diff --git a/playback/cacher.cpp b/playback/cacher.cpp index c2467892b..d5ab7feed 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -318,8 +318,8 @@ void open_clip_worker(Clip* clip) { av_dict_set(&opts, "threads", "auto", 0); } if (clip->stream->codecpar->codec_id == AV_CODEC_ID_H264) { - av_dict_set(&opts, "tune", "fastdecode", 0); - av_dict_set(&opts, "tune", "zerolatency", 0); + av_dict_set(&opts, "tune", "fastdecode", 0); + av_dict_set(&opts, "tune", "zerolatency", 0); } // Open codec diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index e5ac70814..35831a5f2 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -12,6 +12,7 @@ #include "io/media.h" #include "ui_timeline.h" #include "playback/cacher.h" +#include "io/config.h" #include #include @@ -64,7 +65,75 @@ void ViewerWidget::paintEvent(QPaintEvent *e) { if (!rendering) { makeCurrent(); QOpenGLWidget::paintEvent(e); - } + } +} + +void ViewerWidget::drawTitleSafeArea() { + double halfWidth = 0.5; + double halfHeight = 0.5; + double viewportAr = (double) width() / (double) height(); + double halfAr = viewportAr*0.5; + + if (config.use_custom_title_safe_ratio && config.custom_title_safe_ratio > 0) { + if (config.custom_title_safe_ratio > viewportAr) { + halfHeight = (config.custom_title_safe_ratio/viewportAr)*0.5; + } else { + halfWidth = (viewportAr/config.custom_title_safe_ratio)*0.5; + } + } + + glLoadIdentity(); + glOrtho(-halfWidth, halfWidth, halfHeight, -halfHeight, -1, 1); + + glColor3f(0.5, 0.5, 0.5); + glBegin(GL_LINES); + + // action safe rectangle + glVertex2d(-0.45, -0.45); + glVertex2d(0.45, -0.45); + glVertex2d(0.45, -0.45); + glVertex2d(0.45, 0.45); + glVertex2d(0.45, 0.45); + glVertex2d(-0.45, 0.45); + glVertex2d(-0.45, 0.45); + glVertex2d(-0.45, -0.45); + + // title safe rectangle + glVertex2d(-0.4, -0.4); + glVertex2d(0.4, -0.4); + glVertex2d(0.4, -0.4); + glVertex2d(0.4, 0.4); + glVertex2d(0.4, 0.4); + glVertex2d(-0.4, 0.4); + glVertex2d(-0.4, 0.4); + glVertex2d(-0.4, -0.4); + + // horizontal centers + glVertex2d(-0.45, 0); + glVertex2d(-0.375, 0); + glVertex2d(0.45, 0); + glVertex2d(0.375, 0); + + // vertical centers + glVertex2d(0, -0.45); + glVertex2d(0, -0.375); + glVertex2d(0, 0.45); + glVertex2d(0, 0.375); + + glEnd(); + + // center cross + glLoadIdentity(); + glOrtho(-halfAr, halfAr, 0.5, -0.5, -1, 1); + + glBegin(GL_LINES); + + glVertex2d(-0.05, 0); + glVertex2d(0.05, 0); + glVertex2d(0, -0.05); + glVertex2d(0, 0.05); + + glEnd(); } GLuint ViewerWidget::draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture) { @@ -362,6 +431,10 @@ void ViewerWidget::paintGL() { } } + if (config.show_title_safe_area) { + drawTitleSafeArea(); + } + glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); } while (loop); diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index 17d9dff64..f50ea916d 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -29,6 +29,7 @@ protected: // void resizeGL(int w, int h); private: QTimer retry_timer; + void drawTitleSafeArea(); private slots: void retry(); void deleteFunction();