From 64b7c2e30a6adc62c373b9dcc7f39310f10ed994 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Sep 2018 00:14:04 +0100 Subject: [PATCH] Add basic quality option for x264 export. --- src/lib/ffmpeg_encoder.cc | 3 ++- src/lib/ffmpeg_encoder.h | 2 +- src/tools/dcpomatic.cc | 2 +- src/wx/export_dialog.cc | 25 +++++++++++++++++++++++++ src/wx/export_dialog.h | 3 +++ src/wx/table_dialog.cc | 3 ++- src/wx/table_dialog.h | 2 +- test/ffmpeg_encoder_test.cc | 16 ++++++++-------- 8 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/lib/ffmpeg_encoder.cc b/src/lib/ffmpeg_encoder.cc index 71063c123..009a83def 100644 --- a/src/lib/ffmpeg_encoder.cc +++ b/src/lib/ffmpeg_encoder.cc @@ -49,7 +49,7 @@ force_pixel_format (AVPixelFormat, AVPixelFormat out) return out; } -FFmpegEncoder::FFmpegEncoder (shared_ptr film, weak_ptr job, boost::filesystem::path output, Format format, bool mixdown_to_stereo) +FFmpegEncoder::FFmpegEncoder (shared_ptr film, weak_ptr job, boost::filesystem::path output, Format format, bool mixdown_to_stereo, int x264_crf) : Encoder (film, job) , _video_options (0) , _history (1000) @@ -69,6 +69,7 @@ FFmpegEncoder::FFmpegEncoder (shared_ptr film, weak_ptr job, bo _sample_format = AV_SAMPLE_FMT_FLTP; _video_codec_name = "libx264"; _audio_codec_name = "aac"; + av_dict_set_int (&_video_options, "crf", x264_crf, 0); break; } diff --git a/src/lib/ffmpeg_encoder.h b/src/lib/ffmpeg_encoder.h index b1d07eb7f..51af48d48 100644 --- a/src/lib/ffmpeg_encoder.h +++ b/src/lib/ffmpeg_encoder.h @@ -41,7 +41,7 @@ public: FORMAT_H264 }; - FFmpegEncoder (boost::shared_ptr film, boost::weak_ptr job, boost::filesystem::path output, Format format, bool mixdown_to_stereo); + FFmpegEncoder (boost::shared_ptr film, boost::weak_ptr job, boost::filesystem::path output, Format format, bool mixdown_to_stereo, int x264_crf); void go (); diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 0af65bd26..3d4e5121d 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -834,7 +834,7 @@ private: ExportDialog* d = new ExportDialog (this); if (d->ShowModal() == wxID_OK) { shared_ptr job (new TranscodeJob (_film)); - job->set_encoder (shared_ptr (new FFmpegEncoder (_film, job, d->path(), d->format(), d->mixdown_to_stereo()))); + job->set_encoder (shared_ptr (new FFmpegEncoder (_film, job, d->path(), d->format(), d->mixdown_to_stereo(), d->x264_crf()))); JobManager::instance()->add (job); } d->Destroy (); diff --git a/src/wx/export_dialog.cc b/src/wx/export_dialog.cc index 87a824882..481408578 100644 --- a/src/wx/export_dialog.cc +++ b/src/wx/export_dialog.cc @@ -57,6 +57,16 @@ ExportDialog::ExportDialog (wxWindow* parent) add_spacer (); _mixdown = new wxCheckBox (this, wxID_ANY, _("Mix audio down to stereo")); add (_mixdown, false); + _x264_crf_label[0] = add (_("Quality"), true); + _x264_crf = new wxSlider (this, wxID_ANY, 23, 0, 51, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL | wxSL_LABELS); + add (_x264_crf, false); + add_spacer (); + _x264_crf_label[1] = add (_("0 is best, 51 is worst"), false); + wxFont font = _x264_crf_label[1]->GetFont(); + font.SetStyle(wxFONTSTYLE_ITALIC); + font.SetPointSize(font.GetPointSize() - 1); + _x264_crf_label[1]->SetFont(font); + add (_("Output file"), true); _file = new FilePickerCtrl (this, _("Select output file"), format_filters[0], false); add (_file); @@ -66,6 +76,11 @@ ExportDialog::ExportDialog (wxWindow* parent) } _format->SetSelection (0); + _x264_crf->Enable (false); + for (int i = 0; i < 2; ++i) { + _x264_crf_label[i]->Enable (false); + } + _format->Bind (wxEVT_CHOICE, bind (&ExportDialog::format_changed, this)); _file->Bind (wxEVT_FILEPICKER_CHANGED, bind (&ExportDialog::file_changed, this)); @@ -81,6 +96,10 @@ ExportDialog::format_changed () DCPOMATIC_ASSERT (_format->GetSelection() >= 0 && _format->GetSelection() < FORMATS); _file->SetWildcard (format_filters[_format->GetSelection()]); _file->SetPath (""); + _x264_crf->Enable (_format->GetSelection() == 1); + for (int i = 0; i < 2; ++i) { + _x264_crf_label[i]->Enable (_format->GetSelection() == 1); + } } boost::filesystem::path @@ -104,6 +123,12 @@ ExportDialog::mixdown_to_stereo () const return _mixdown->GetValue (); } +int +ExportDialog::x264_crf () const +{ + return _x264_crf->GetValue (); +} + void ExportDialog::file_changed () { diff --git a/src/wx/export_dialog.h b/src/wx/export_dialog.h index c2498d6a1..c6ccc875e 100644 --- a/src/wx/export_dialog.h +++ b/src/wx/export_dialog.h @@ -33,6 +33,7 @@ public: boost::filesystem::path path () const; FFmpegEncoder::Format format () const; bool mixdown_to_stereo () const; + int x264_crf () const; private: void format_changed (); @@ -40,5 +41,7 @@ private: wxChoice* _format; wxCheckBox* _mixdown; + wxSlider* _x264_crf; + wxStaticText* _x264_crf_label[2]; FilePickerCtrl* _file; }; diff --git a/src/wx/table_dialog.cc b/src/wx/table_dialog.cc index f94fb0fe8..240a997d2 100644 --- a/src/wx/table_dialog.cc +++ b/src/wx/table_dialog.cc @@ -50,7 +50,7 @@ TableDialog::layout () _overall_sizer->SetSizeHints (this); } -void +wxStaticText * #ifdef DCPOMATIC_OSX TableDialog::add (wxString text, bool label) #else @@ -67,6 +67,7 @@ TableDialog::add (wxString text, bool) wxStaticText* m = new wxStaticText (this, wxID_ANY, wxT ("")); m->SetLabelMarkup (text); _table->Add (m, 0, flags, 6); + return m; } void diff --git a/src/wx/table_dialog.h b/src/wx/table_dialog.h index 8969dc561..a5015ee59 100644 --- a/src/wx/table_dialog.h +++ b/src/wx/table_dialog.h @@ -35,7 +35,7 @@ protected: return w; } - void add (wxString text, bool label); + wxStaticText* add (wxString text, bool label); void add_spacer (); void layout (); diff --git a/test/ffmpeg_encoder_test.cc b/test/ffmpeg_encoder_test.cc index b286bbdb4..8bb813713 100644 --- a/test/ffmpeg_encoder_test.cc +++ b/test/ffmpeg_encoder_test.cc @@ -65,7 +65,7 @@ ffmpeg_content_test (int number, boost::filesystem::path content, FFmpegEncoder: film->write_metadata (); shared_ptr job (new TranscodeJob (film)); - FFmpegEncoder encoder (film, job, String::compose("build/test/%1.%2", name, extension), format, false); + FFmpegEncoder encoder (film, job, String::compose("build/test/%1.%2", name, extension), format, false, 23); encoder.go (); } @@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test5) film->write_metadata (); shared_ptr job (new TranscodeJob (film)); - FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test5.mov", FFmpegEncoder::FORMAT_PRORES, false); + FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test5.mov", FFmpegEncoder::FORMAT_PRORES, false, 23); encoder.go (); } @@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test6) film->write_metadata(); shared_ptr job (new TranscodeJob (film)); - FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test6.mov", FFmpegEncoder::FORMAT_PRORES, false); + FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test6.mov", FFmpegEncoder::FORMAT_PRORES, false, 23); encoder.go (); } @@ -154,7 +154,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test7) s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255)); shared_ptr job (new TranscodeJob (film)); - FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test7.mov", FFmpegEncoder::FORMAT_PRORES, false); + FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test7.mov", FFmpegEncoder::FORMAT_PRORES, false, 23); encoder.go (); } @@ -181,7 +181,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test2) film->write_metadata(); shared_ptr job (new TranscodeJob (film)); - FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test2.mp4", FFmpegEncoder::FORMAT_H264, false); + FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test2.mp4", FFmpegEncoder::FORMAT_H264, false, 23); encoder.go (); } @@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test3) film->write_metadata(); shared_ptr job (new TranscodeJob (film)); - FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test3.mp4", FFmpegEncoder::FORMAT_H264, false); + FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test3.mp4", FFmpegEncoder::FORMAT_H264, false, 23); encoder.go (); } @@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test4) film->set_container(Ratio::from_id("185")); shared_ptr job(new TranscodeJob(film)); - FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test4.mp4", FFmpegEncoder::FORMAT_H264, false); + FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test4.mp4", FFmpegEncoder::FORMAT_H264, false, 23); encoder.go(); } @@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test5) Rs->audio->set_mapping (map); shared_ptr job (new TranscodeJob (film)); - FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test5.mp4", FFmpegEncoder::FORMAT_H264, true); + FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test5.mp4", FFmpegEncoder::FORMAT_H264, true, 23); encoder.go (); check_ffmpeg ("build/test/ffmpeg_encoder_h264_test5.mp4", "test/data/ffmpeg_encoder_h264_test5.mp4", 1); -- 2.30.2