Add basic quality option for x264 export.
authorCarl Hetherington <cth@carlh.net>
Sun, 2 Sep 2018 23:14:04 +0000 (00:14 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 2 Sep 2018 23:14:04 +0000 (00:14 +0100)
src/lib/ffmpeg_encoder.cc
src/lib/ffmpeg_encoder.h
src/tools/dcpomatic.cc
src/wx/export_dialog.cc
src/wx/export_dialog.h
src/wx/table_dialog.cc
src/wx/table_dialog.h
test/ffmpeg_encoder_test.cc

index 71063c12371d3c4765e42c5120089bca1b051af7..009a83def13b617c9d86a08e46bb717fd61bc774 100644 (file)
@@ -49,7 +49,7 @@ force_pixel_format (AVPixelFormat, AVPixelFormat out)
        return out;
 }
 
-FFmpegEncoder::FFmpegEncoder (shared_ptr<const Film> film, weak_ptr<Job> job, boost::filesystem::path output, Format format, bool mixdown_to_stereo)
+FFmpegEncoder::FFmpegEncoder (shared_ptr<const Film> film, weak_ptr<Job> 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<const Film> film, weak_ptr<Job> 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;
        }
 
index b1d07eb7f65bdeff0ebaf414be6a29afbffcf6ac..51af48d48e6050b62d308e5ce20836d95ff971b3 100644 (file)
@@ -41,7 +41,7 @@ public:
                FORMAT_H264
        };
 
-       FFmpegEncoder (boost::shared_ptr<const Film> film, boost::weak_ptr<Job> job, boost::filesystem::path output, Format format, bool mixdown_to_stereo);
+       FFmpegEncoder (boost::shared_ptr<const Film> film, boost::weak_ptr<Job> job, boost::filesystem::path output, Format format, bool mixdown_to_stereo, int x264_crf);
 
        void go ();
 
index 0af65bd2611cafa0bedee24e6241563a2db6f5b4..3d4e5121d6fbca1abc61276c008a0e007844a727 100644 (file)
@@ -834,7 +834,7 @@ private:
                ExportDialog* d = new ExportDialog (this);
                if (d->ShowModal() == wxID_OK) {
                        shared_ptr<TranscodeJob> job (new TranscodeJob (_film));
-                       job->set_encoder (shared_ptr<FFmpegEncoder> (new FFmpegEncoder (_film, job, d->path(), d->format(), d->mixdown_to_stereo())));
+                       job->set_encoder (shared_ptr<FFmpegEncoder> (new FFmpegEncoder (_film, job, d->path(), d->format(), d->mixdown_to_stereo(), d->x264_crf())));
                        JobManager::instance()->add (job);
                }
                d->Destroy ();
index 87a8248822b3fbd5bb86353008f3b5a7a7fe9254..4814085781abd2df857a5d4071b4a1bf300a2a6c 100644 (file)
@@ -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 ()
 {
index c2498d6a149498ded640a002ad633125d52e34e1..c6ccc875ed38346eb858ebaf4ed74b67708de8e1 100644 (file)
@@ -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;
 };
index f94fb0fe83026816659db61e6caa771d80e4fd1e..240a997d2fb7cbae392502d2df92b4973c52e1de 100644 (file)
@@ -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
index 8969dc56134a8bdeba72c9e815068f67955e8f07..a5015ee59c02f4921233922455a5e774b5fbce38 100644 (file)
@@ -35,7 +35,7 @@ protected:
                return w;
        }
 
-       void add (wxString text, bool label);
+       wxStaticText* add (wxString text, bool label);
        void add_spacer ();
 
        void layout ();
index b286bbdb4ed387e23aeb58fb8a5b3ffe532950ea..8bb813713c9b73f3297b8c1c51ed448d7d34c918 100644 (file)
@@ -65,7 +65,7 @@ ffmpeg_content_test (int number, boost::filesystem::path content, FFmpegEncoder:
 
        film->write_metadata ();
        shared_ptr<Job> 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> 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> 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> 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> 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> 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> 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> 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);