*/
-Hints::Hints (weak_ptr<const Film> film)
- : WeakConstFilm (film)
- , _writer (new Writer(film, weak_ptr<Job>(), true))
- , _long_ccap (false)
- , _overlap_ccap (false)
- , _too_many_ccap_lines (false)
- , _early_subtitle (false)
- , _short_subtitle (false)
- , _subtitles_too_close (false)
- , _too_many_subtitle_lines (false)
- , _long_subtitle (false)
+Hints::Hints (weak_ptr<const Film> weak_film)
+ : WeakConstFilm (weak_film)
+ , _writer (new Writer(weak_film, weak_ptr<Job>(), true))
+ , _analyser (film(), film()->playlist(), true, [](float) {})
, _stop (false)
{
int scope = 0;
for (auto i: film()->content()) {
if (i->video) {
- Ratio const * r = Ratio::nearest_from_ratio(i->video->scaled_size(film()->frame_size()).ratio());
+ 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") {
}
-void
+/** @return true if the loudness could be checked, false if it could not because no analysis was available */
+bool
Hints::check_loudness ()
{
auto path = film()->audio_analysis_path(film()->playlist());
- if (boost::filesystem::exists (path)) {
- try {
- auto an = make_shared<AudioAnalysis>(path);
+ if (!boost::filesystem::exists(path)) {
+ return false;
+ }
- string ch;
+ try {
+ auto an = make_shared<AudioAnalysis>(path);
- auto sample_peak = an->sample_peak ();
- auto true_peak = an->true_peak ();
+ string ch;
- for (size_t i = 0; i < sample_peak.size(); ++i) {
- float const peak = max (sample_peak[i].peak, true_peak.empty() ? 0 : true_peak[i]);
- float const peak_dB = linear_to_db(peak) + an->gain_correction(film()->playlist());
- if (peak_dB > -3) {
- ch += dcp::raw_convert<string> (short_audio_channel_name (i)) + ", ";
- }
+ auto sample_peak = an->sample_peak ();
+ auto true_peak = an->true_peak ();
+
+ for (size_t i = 0; i < sample_peak.size(); ++i) {
+ float const peak = max (sample_peak[i].peak, true_peak.empty() ? 0 : true_peak[i]);
+ float const peak_dB = linear_to_db(peak) + an->gain_correction(film()->playlist());
+ if (peak_dB > -3) {
+ ch += dcp::raw_convert<string>(short_audio_channel_name(i)) + ", ";
}
+ }
- ch = ch.substr (0, ch.length() - 2);
+ ch = ch.substr (0, ch.length() - 2);
- if (!ch.empty ()) {
- hint (String::compose (
- _("Your audio level is very high (on %1). You should reduce the gain of your audio content."),
- ch
- )
- );
- }
- } catch (OldFormatError& e) {
- /* The audio analysis is too old to load in; just skip this hint as if
- it had never been run.
- */
+ if (!ch.empty ()) {
+ hint (String::compose (
+ _("Your audio level is very high (on %1). You should reduce the gain of your audio content."),
+ ch
+ )
+ );
}
+ } catch (OldFormatError& e) {
+ /* The audio analysis is too old to load in */
+ return false;
}
+
+ return true;
}
void
Hints::thread ()
+try
{
auto film = _film.lock ();
if (!film) {
check_speed_up ();
check_vob ();
check_3d_in_2d ();
- check_loudness ();
+ auto const check_loudness_done = check_loudness ();
check_ffec_and_ffmc_in_smpte_feature ();
check_out_of_range_markers ();
check_text_languages ();
- emit (bind(boost::ref(Progress), _("Examining closed captions")));
+ if (check_loudness_done) {
+ emit (bind(boost::ref(Progress), _("Examining subtitles and closed captions")));
+ } else {
+ emit (bind(boost::ref(Progress), _("Examining audio, subtitles and closed captions")));
+ }
auto player = make_shared<Player>(film);
player->set_ignore_video ();
- player->set_ignore_audio ();
+ if (check_loudness_done) {
+ /* We don't need to analyse audio because we already loaded a suitable analysis */
+ player->set_ignore_audio ();
+ }
+ player->Audio.connect (bind(&Hints::audio, this, _1, _2));
player->Text.connect (bind(&Hints::text, this, _1, _2, _3, _4));
struct timeval last_pulse;
gettimeofday (&last_pulse, 0);
- try {
- while (!player->pass()) {
+ while (!player->pass()) {
- struct timeval now;
- gettimeofday (&now, 0);
- if ((seconds(now) - seconds(last_pulse)) > 1) {
- if (_stop) {
- break;
- }
- emit (bind (boost::ref(Pulse)));
- last_pulse = now;
+ struct timeval now;
+ gettimeofday (&now, 0);
+ if ((seconds(now) - seconds(last_pulse)) > 1) {
+ if (_stop) {
+ return;
}
+ emit (bind (boost::ref(Pulse)));
+ last_pulse = now;
}
- } catch (...) {
- store_current ();
+ }
+
+ if (!check_loudness_done) {
+ _analyser.finish ();
+ _analyser.get().write(film->audio_analysis_path(film->playlist()));
+ check_loudness ();
}
_writer->write (player->get_subtitle_fonts());
+ 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."));
+ } else if (_very_long_subtitle) {
+ hint (_("At least one of your subtitle lines has more than 79 characters. You should make each line 79 characters at most in length."));
+ }
+
bool ccap_xml_too_big = false;
bool ccap_mxf_too_big = false;
bool subs_mxf_too_big = false;
boost::filesystem::path dcp_dir = film->dir("hints") / dcpomatic::get_process_id();
boost::filesystem::remove_all (dcp_dir);
- try {
- _writer->finish (film->dir("hints") / dcpomatic::get_process_id());
- } catch (...) {
- store_current ();
- emit (bind(boost::ref(Finished)));
- return;
- }
+ _writer->finish (film->dir("hints") / dcpomatic::get_process_id());
dcp::DCP dcp (dcp_dir);
dcp.read ();
emit (bind(boost::ref(Finished)));
}
+catch (boost::thread_interrupted)
+{
+ /* The Hints object is being destroyed before it has finished, so just give up */
+}
+catch (...)
+{
+ store_current ();
+}
void
Hints::hint (string h)
emit(bind(boost::ref(Hint), h));
}
+
+void
+Hints::audio (shared_ptr<AudioBuffers> audio, DCPTime time)
+{
+ _analyser.analyse (audio, time);
+}
+
+
void
Hints::text (PlayerText text, TextType type, optional<DCPTextTrack> track, DCPTimePeriod period)
{
longest_line = max (longest_line, i.text().length());
}
- if (longest_line > 52 && !_long_subtitle) {
+ if (longest_line > 52) {
_long_subtitle = true;
- hint (_("At least one of your subtitle lines has more than 52 characters. It is advisable to make each line 52 characters at most in length."));
+ }
+
+ if (longest_line > 79) {
+ _very_long_subtitle = true;
}
_last_subtitle = period;
for (auto j: i->text) {
if (j->use() && !j->language()) {
hint (_("At least one piece of subtitle or closed caption content has no specified language. "
- "It is advisable to set the language for each piece of subtitle or closed caption content in the \"Content→Timed Text\" tab"));
+ "It is advisable to set the language for each piece of subtitle or closed caption content "
+ "in the \"Content→Timed text\", \"Content→Open subtitles\" or \"Content→Closed captions\" tab."));
return;
}
}