Allow specification of video bit rate separately for J2K and MPEG2.
[dcpomatic.git] / src / lib / hints.cc
index b4d94dbcc3d03ab4ab06de1045c94cdd2b7f153f..8e678fdf15987916c48f48593d9a9b1680d28c0a 100644 (file)
@@ -35,6 +35,7 @@
 #include "player.h"
 #include "ratio.h"
 #include "text_content.h"
+#include "variant.h"
 #include "video_content.h"
 #include "writer.h"
 #include <dcp/cpl.h>
@@ -107,7 +108,13 @@ void
 Hints::check_few_audio_channels ()
 {
        if (film()->audio_channels() < 6) {
-               hint (_("Your DCP has fewer than 6 audio channels.  This may cause problems on some projectors.  You may want to set the DCP to have 6 channels.  It does not matter if your content has fewer channels, as DCP-o-matic will fill the extras with silence."));
+               hint(
+                       variant::insert_dcpomatic(
+                               _("Your DCP has fewer than 6 audio channels.  This may cause problems on some projectors.  "
+                                 "You may want to set the DCP to have 6 channels.  It does not matter if your content has "
+                                 "fewer channels, as %1 will fill the extras with silence.")
+                               )
+                   );
        }
 }
 
@@ -117,7 +124,12 @@ Hints::check_upmixers ()
 {
        auto ap = film()->audio_processor();
        if (ap && (ap->id() == "stereo-5.1-upmix-a" || ap->id() == "stereo-5.1-upmix-b")) {
-               hint (_("You are using DCP-o-matic's stereo-to-5.1 upmixer.  This is experimental and may result in poor-quality audio.  If you continue, you should listen to the resulting DCP in a cinema to make sure that it sounds good."));
+               hint(variant::insert_dcpomatic(
+                               _("You are using %1's stereo-to-5.1 upmixer.  This is experimental and "
+                                 "may result in poor-quality audio.  If you continue, you should listen to the "
+                                 "resulting DCP in a cinema to make sure that it sounds good.")
+                               )
+                   );
        }
 }
 
@@ -128,8 +140,8 @@ Hints::check_incorrect_container ()
        int narrower_than_scope = 0;
        int scope = 0;
        for (auto i: film()->content()) {
-               if (i->video) {
-                       auto const r = Ratio::nearest_from_ratio(i->video->scaled_size(film()->frame_size()).ratio());
+               if (i->video && i->video->size()) {
+                       auto const r = Ratio::nearest_from_ratio(i->video->scaled_size(film()->frame_size())->ratio());
                        if (r && r->id() == "239") {
                                ++scope;
                        } else if (r && r->id() != "239" && r->id() != "235" && r->id() != "190") {
@@ -161,10 +173,10 @@ Hints::check_unusual_container ()
 
 
 void
-Hints::check_high_j2k_bandwidth ()
+Hints::check_high_video_bit_rate()
 {
-       if (film()->j2k_bandwidth() >= 245000000) {
-               hint (_("A few projectors have problems playing back very high bit-rate DCPs.  It is a good idea to drop the JPEG2000 bandwidth down to about 200Mbit/s; this is unlikely to have any visible effect on the image."));
+       if (film()->video_encoding() == VideoEncoding::JPEG2000 && film()->video_bit_rate(VideoEncoding::JPEG2000) >= 245000000) {
+               hint (_("A few projectors have problems playing back very high bit-rate DCPs.  It is a good idea to drop the video bit rate down to about 200Mbit/s; this is unlikely to have any visible effect on the image."));
        }
 }
 
@@ -370,77 +382,105 @@ Hints::check_out_of_range_markers ()
 
 
 void
-Hints::thread ()
-try
+Hints::scan_content(shared_ptr<const Film> film)
 {
-       start_of_thread ("Hints");
+       auto const check_loudness_done = check_loudness();
 
-       auto film = _film.lock ();
-       if (!film) {
-               return;
-       }
+       auto content = film->playlist()->content();
+       auto iter = std::find_if(content.begin(), content.end(), [](shared_ptr<const Content> content) {
+               auto text_iter = std::find_if(content->text.begin(), content->text.end(), [](shared_ptr<const TextContent> text) {
+                       return text->use();
+               });
+               return text_iter != content->text.end();
+       });
 
-       auto content = film->content ();
+       auto const have_text = iter != content.end();
 
-       check_certificates ();
-       check_interop ();
-       check_big_font_files ();
-       check_few_audio_channels ();
-       check_upmixers ();
-       check_incorrect_container ();
-       check_unusual_container ();
-       check_high_j2k_bandwidth ();
-       check_frame_rate ();
-       check_4k_3d ();
-       check_speed_up ();
-       check_vob ();
-       check_3d_in_2d ();
-       auto const check_loudness_done = check_loudness ();
-       check_ffec_and_ffmc_in_smpte_feature ();
-       check_out_of_range_markers ();
-       check_subtitle_languages();
-       check_audio_language ();
-       check_8_or_16_audio_channels();
+       if (check_loudness_done && !have_text) {
+               /* We don't need to check loudness, and we don't have any active text to check,
+                * so a scan of the content is pointless.
+                */
+               return;
+       }
 
-       if (check_loudness_done) {
+       if (check_loudness_done && have_text) {
                emit (bind(boost::ref(Progress), _("Examining subtitles and closed captions")));
+       } else if (!check_loudness_done && !have_text) {
+               emit (bind(boost::ref(Progress), _("Examining audio")));
        } else {
                emit (bind(boost::ref(Progress), _("Examining audio, subtitles and closed captions")));
        }
 
        auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
-       player->set_ignore_video ();
+       player->set_ignore_video();
        if (check_loudness_done || _disable_audio_analysis) {
                /* We don't need to analyse audio because we already loaded a suitable analysis */
-               player->set_ignore_audio ();
+               player->set_ignore_audio();
+       } else {
+               /* Send auto to the analyser to check loudness */
+               player->Audio.connect(bind(&Hints::audio, this, _1, _2));
        }
-       player->Audio.connect (bind(&Hints::audio, this, _1, _2));
-       player->Text.connect (bind(&Hints::text, this, _1, _2, _3, _4));
+       player->Text.connect(bind(&Hints::text, this, _1, _2, _3, _4));
 
        struct timeval last_pulse;
-       gettimeofday (&last_pulse, 0);
+       gettimeofday(&last_pulse, 0);
 
-       _writer->write (player->get_subtitle_fonts());
+       _writer->write(player->get_subtitle_fonts());
 
        while (!player->pass()) {
 
                struct timeval now;
-               gettimeofday (&now, 0);
+               gettimeofday(&now, 0);
                if ((seconds(now) - seconds(last_pulse)) > 1) {
                        if (_stop) {
                                return;
                        }
-                       emit (bind (boost::ref(Pulse)));
+                       emit(bind(boost::ref(Pulse)));
                        last_pulse = now;
                }
        }
 
        if (!check_loudness_done) {
-               _analyser.finish ();
+               _analyser.finish();
                _analyser.get().write(film->audio_analysis_path(film->playlist()));
-               check_loudness ();
+               check_loudness();
+       }
+}
+
+
+void
+Hints::thread ()
+try
+{
+       start_of_thread ("Hints");
+
+       auto film = _film.lock ();
+       if (!film) {
+               return;
        }
 
+       auto content = film->content ();
+
+       check_certificates ();
+       check_interop ();
+       check_big_font_files ();
+       check_few_audio_channels ();
+       check_upmixers ();
+       check_incorrect_container ();
+       check_unusual_container ();
+       check_high_video_bit_rate();
+       check_frame_rate ();
+       check_4k_3d ();
+       check_speed_up ();
+       check_vob ();
+       check_3d_in_2d ();
+       check_ffec_and_ffmc_in_smpte_feature ();
+       check_out_of_range_markers ();
+       check_subtitle_languages();
+       check_audio_language ();
+       check_8_or_16_audio_channels();
+
+       scan_content(film);
 
        if (_long_subtitle && !_very_long_subtitle) {
                hint (_("At least one of your subtitle lines has more than 52 characters.  It is recommended to make each line 52 characters at most in length."));
@@ -690,16 +730,20 @@ Hints::check_certificates ()
 
        switch (*bad) {
        case Config::BAD_SIGNER_UTF8_STRINGS:
-               hint(_("The certificate chain that DCP-o-matic uses for signing DCPs and KDMs contains a small error "
-                      "which will prevent DCPs from being validated correctly on some systems.  It is advisable to "
-                      "re-create the signing certificate chain by clicking the \"Re-make certificates and key...\" "
-                      "button in the Keys page of Preferences."));
+               hint(variant::insert_dcpomatic(
+                               _("The certificate chain that %1 uses for signing DCPs and KDMs contains a small error "
+                                 "which will prevent DCPs from being validated correctly on some systems.  It is advisable to "
+                                 "re-create the signing certificate chain by clicking the \"Re-make certificates and key...\" "
+                                 "button in the Keys page of Preferences.")
+                               ));
                break;
        case Config::BAD_SIGNER_VALIDITY_TOO_LONG:
-               hint(_("The certificate chain that DCP-o-matic uses for signing DCPs and KDMs has a validity period "
-                      "that is too long.  This will cause problems playing back DCPs on some systems. "
-                      "It is advisable to re-create the signing certificate chain by clicking the "
-                      "\"Re-make certificates and key...\" button in the Keys page of Preferences."));
+               hint(variant::insert_dcpomatic(
+                               _("The certificate chain that %1 uses for signing DCPs and KDMs has a validity period "
+                                 "that is too long.  This will cause problems playing back DCPs on some systems. "
+                                 "It is advisable to re-create the signing certificate chain by clicking the "
+                                 "\"Re-make certificates and key...\" button in the Keys page of Preferences.")
+                               ));
                break;
        default:
                /* Some bad situations can't happen here as DCP-o-matic would have refused to start until they are fixed */