X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Futil.cc;h=4ffe3bd12bb8ed4f76092286f8aad08ce4fe0691;hb=3c86d70cf46ca11212ae2e2f4d711db0f478c2f5;hp=d20fd7dc7b0f4d94cb830dfaf6db4d07683d446d;hpb=b81241ce69a689629307832f802ac4faa6ed885f;p=dcpomatic.git diff --git a/src/lib/util.cc b/src/lib/util.cc index d20fd7dc7..4ffe3bd12 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -36,6 +36,7 @@ #include "digester.h" #include "audio_processor.h" #include "compose.hpp" +#include "audio_buffers.h" #include #include #include @@ -44,6 +45,7 @@ #include extern "C" { #include +#include #include } #include @@ -53,6 +55,7 @@ extern "C" { #include #include #include +#include #include #include #ifdef DCPOMATIC_WINDOWS @@ -87,6 +90,7 @@ using std::pair; using std::cout; using std::bad_alloc; using std::set_terminate; +using std::make_pair; using boost::shared_ptr; using boost::thread; using boost::optional; @@ -321,6 +325,7 @@ dcpomatic_setup () SetUnhandledExceptionFilter(exception_handler); #endif + av_register_all (); avfilter_register_all (); #ifdef DCPOMATIC_OSX @@ -422,7 +427,7 @@ digest_head_tail (vector files, boost::uintmax_t size) while (i < int64_t (files.size()) && to_do > 0) { FILE* f = fopen_boost (files[i], "rb"); if (!f) { - throw OpenFileError (files[i].string()); + throw OpenFileError (files[i].string(), errno, true); } boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i])); @@ -442,7 +447,7 @@ digest_head_tail (vector files, boost::uintmax_t size) while (i >= 0 && to_do > 0) { FILE* f = fopen_boost (files[i], "rb"); if (!f) { - throw OpenFileError (files[i].string()); + throw OpenFileError (files[i].string(), errno, true); } boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i])); @@ -461,7 +466,7 @@ digest_head_tail (vector files, boost::uintmax_t size) /** Round a number up to the nearest multiple of another number. * @param c Index. - * @param s Array of numbers to round, indexed by c. + * @param stride Array of numbers to round, indexed by c. * @param t Multiple to round to. * @return Rounded number. */ @@ -485,8 +490,7 @@ audio_channel_name (int c) DCPOMATIC_ASSERT (MAX_DCP_AUDIO_CHANNELS == 16); /// TRANSLATORS: these are the names of audio channels; Lfe (sub) is the low-frequency - /// enhancement channel (sub-woofer). HI is the hearing-impaired audio track and - /// VI is the visually-impaired audio track (audio describe). + /// enhancement channel (sub-woofer). string const channels[] = { _("Left"), _("Right"), @@ -509,6 +513,38 @@ audio_channel_name (int c) return channels[c]; } +string +short_audio_channel_name (int c) +{ + DCPOMATIC_ASSERT (MAX_DCP_AUDIO_CHANNELS == 16); + + /// TRANSLATORS: these are short names of audio channels; Lfe is the low-frequency + /// enhancement channel (sub-woofer). HI is the hearing-impaired audio track and + /// VI is the visually-impaired audio track (audio describe). DBP is the D-BOX + /// primary channel and DBS is the D-BOX secondary channel. + string const channels[] = { + _("L"), + _("R"), + _("C"), + _("Lfe"), + _("Ls"), + _("Rs"), + _("HI"), + _("VI"), + _("Lc"), + _("Rc"), + _("BsL"), + _("BsR"), + _("DBP"), + _("DBS"), + "", + "" + }; + + return channels[c]; +} + + bool valid_image_file (boost::filesystem::path f) { @@ -525,6 +561,18 @@ valid_image_file (boost::filesystem::path f) ); } +bool +valid_sound_file (boost::filesystem::path f) +{ + if (boost::starts_with (f.leaf().string(), "._")) { + return false; + } + + string ext = f.extension().string(); + transform (ext.begin(), ext.end(), ext.begin(), ::tolower); + return (ext == ".wav" || ext == ".mp3" || ext == ".aif" || ext == ".aiff"); +} + bool valid_j2k_file (boost::filesystem::path f) { @@ -536,16 +584,8 @@ valid_j2k_file (boost::filesystem::path f) string tidy_for_filename (string f) { - string t; - for (size_t i = 0; i < f.length(); ++i) { - if (isalnum (f[i]) || f[i] == '_' || f[i] == '-') { - t += f[i]; - } else { - t += '_'; - } - } - - return t; + boost::replace_if (f, boost::is_any_of ("\\/:"), '_'); + return f; } dcp::Size @@ -619,13 +659,12 @@ video_asset_filename (shared_ptr asset, int reel_index, int r { dcp::NameFormat::Map values; values['t'] = "j2c"; - values['i'] = asset->id(); values['r'] = raw_convert (reel_index + 1); values['n'] = raw_convert (reel_count); if (summary) { - values['c'] = summary.get(); + values['c'] = careful_string_filter (summary.get()); } - return Config::instance()->dcp_asset_filename_format().get(values) + ".mxf"; + return Config::instance()->dcp_asset_filename_format().get(values, "_" + asset->id() + ".mxf"); } string @@ -633,13 +672,12 @@ audio_asset_filename (shared_ptr asset, int reel_index, int ree { dcp::NameFormat::Map values; values['t'] = "pcm"; - values['i'] = asset->id(); values['r'] = raw_convert (reel_index + 1); values['n'] = raw_convert (reel_count); if (summary) { - values['c'] = summary.get(); + values['c'] = careful_string_filter (summary.get()); } - return Config::instance()->dcp_asset_filename_format().get(values) + ".mxf"; + return Config::instance()->dcp_asset_filename_format().get(values, "_" + asset->id() + ".mxf"); } float @@ -654,8 +692,69 @@ relaxed_string_to_float (string s) } } -bool -string_not_empty (string s) +string +careful_string_filter (string s) +{ + /* Filter out `bad' characters which `may' cause problems with some systems (either for DCP name or filename). + There's no apparent list of what really is allowed, so this is a guess. + Safety first and all that. + */ + + string out; + string const allowed = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_%."; + for (size_t i = 0; i < s.size(); ++i) { + if (allowed.find (s[i]) != string::npos) { + out += s[i]; + } + } + + return out; +} + +/** @param mapped List of mapped audio channels from a Film. + * @param channels Total number of channels in the Film. + * @return First: number of non-LFE channels, second: number of LFE channels. + */ +pair +audio_channel_types (list mapped, int channels) +{ + int non_lfe = 0; + int lfe = 0; + + BOOST_FOREACH (int i, mapped) { + if (i >= channels) { + /* This channel is mapped but is not included in the DCP */ + continue; + } + + if (static_cast (i) == dcp::LFE) { + ++lfe; + } else { + ++non_lfe; + } + } + + return make_pair (non_lfe, lfe); +} + +shared_ptr +remap (shared_ptr input, int output_channels, AudioMapping map) { - return !s.empty (); + shared_ptr mapped (new AudioBuffers (output_channels, input->frames())); + mapped->make_silent (); + + for (int i = 0; i < map.input_channels(); ++i) { + for (int j = 0; j < mapped->channels(); ++j) { + if (map.get (i, static_cast (j)) > 0) { + mapped->accumulate_channel ( + input.get(), + i, + static_cast (j), + map.get (i, static_cast (j)) + ); + } + } + } + + return mapped; }