X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_content.cc;h=6383fe58b6736a56c67c696c085c146383517c99;hb=b58ea0495d72d654161958e515dc6c5ba9992b80;hp=86965ff4952b7edaa3fd56437ec0b2f855012d00;hpb=df17bbd25da69fc38eb2dcd8b4a2531cf0bab0bc;p=dcpomatic.git diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 86965ff49..6383fe58b 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -45,8 +45,6 @@ extern "C" { #include "i18n.h" -#define LOG_GENERAL(...) film->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL); - using std::string; using std::vector; using std::list; @@ -63,8 +61,9 @@ int const FFmpegContentProperty::SUBTITLE_STREAMS = 100; int const FFmpegContentProperty::SUBTITLE_STREAM = 101; int const FFmpegContentProperty::FILTERS = 102; -FFmpegContent::FFmpegContent (shared_ptr film, boost::filesystem::path p) - : Content (film, p) +FFmpegContent::FFmpegContent (boost::filesystem::path p) + : Content (p) + , _encrypted (false) { } @@ -80,12 +79,12 @@ get_optional_enum (cxml::ConstNodePtr node, string name) return static_cast(*v); } -FFmpegContent::FFmpegContent (shared_ptr film, cxml::ConstNodePtr node, int version, list& notes) - : Content (film, node) +FFmpegContent::FFmpegContent (cxml::ConstNodePtr node, int version, list& notes) + : Content (node) { video = VideoContent::from_xml (this, node, version); audio = AudioContent::from_xml (this, node, version); - caption = TextContent::from_xml (this, node, version); + text = TextContent::from_xml (this, node, version); list c = node->node_children ("SubtitleStream"); for (list::const_iterator i = c.begin(); i != c.end(); ++i) { @@ -125,22 +124,23 @@ FFmpegContent::FFmpegContent (shared_ptr film, cxml::ConstNodePtr no _color_trc = get_optional_enum(node, "ColorTransferCharacteristic"); _colorspace = get_optional_enum(node, "Colorspace"); _bits_per_pixel = node->optional_number_child ("BitsPerPixel"); - + _decryption_key = node->optional_string_child ("DecryptionKey"); + _encrypted = node->optional_bool_child("Encrypted").get_value_or(false); } -FFmpegContent::FFmpegContent (shared_ptr film, vector > c) - : Content (film, c) +FFmpegContent::FFmpegContent (vector > c) + : Content (c) { vector >::const_iterator i = c.begin (); bool need_video = false; bool need_audio = false; - bool need_caption = false; + bool need_text = false; if (i != c.end ()) { need_video = static_cast ((*i)->video); need_audio = static_cast ((*i)->audio); - need_caption = !(*i)->caption.empty(); + need_text = !(*i)->text.empty(); } while (i != c.end ()) { @@ -150,8 +150,8 @@ FFmpegContent::FFmpegContent (shared_ptr film, vector ((*i)->audio)) { throw JoinError (_("Content to be joined must all have or not have audio")); } - if (need_caption != !(*i)->caption.empty()) { - throw JoinError (_("Content to be joined must all have or not have captions")); + if (need_text != !(*i)->text.empty()) { + throw JoinError (_("Content to be joined must all have or not have subtitles or captions")); } ++i; } @@ -162,8 +162,8 @@ FFmpegContent::FFmpegContent (shared_ptr film, vector (new TextContent (this, c))); + if (need_text) { + text.push_back (shared_ptr (new TextContent (this, c))); } shared_ptr ref = dynamic_pointer_cast (c[0]); @@ -171,7 +171,7 @@ FFmpegContent::FFmpegContent (shared_ptr film, vector fc = dynamic_pointer_cast (c[i]); - if (fc->only_caption() && fc->only_caption()->use() && *(fc->_subtitle_stream.get()) != *(ref->_subtitle_stream.get())) { + if (fc->only_text() && fc->only_text()->use() && *(fc->_subtitle_stream.get()) != *(ref->_subtitle_stream.get())) { throw JoinError (_("Content to be joined must use the same subtitle stream.")); } } @@ -187,6 +187,7 @@ FFmpegContent::FFmpegContent (shared_ptr film, vector_color_trc; _colorspace = ref->_colorspace; _bits_per_pixel = ref->_bits_per_pixel; + _encrypted = ref->_encrypted; } void @@ -209,8 +210,8 @@ FFmpegContent::as_xml (xmlpp::Node* node, bool with_paths) const } } - if (only_caption()) { - only_caption()->as_xml (node); + if (only_text()) { + only_text()->as_xml (node); } boost::mutex::scoped_lock lm (_mutex); @@ -246,14 +247,23 @@ FFmpegContent::as_xml (xmlpp::Node* node, bool with_paths) const if (_bits_per_pixel) { node->add_child("BitsPerPixel")->add_child_text (raw_convert (*_bits_per_pixel)); } + if (_decryption_key) { + node->add_child("DecryptionKey")->add_child_text (_decryption_key.get()); + } + if (_encrypted) { + node->add_child("Encypted")->add_child_text ("1"); + } } void -FFmpegContent::examine (shared_ptr job) +FFmpegContent::examine (shared_ptr film, shared_ptr job) { + ChangeSignaller cc1 (this, FFmpegContentProperty::SUBTITLE_STREAMS); + ChangeSignaller cc2 (this, FFmpegContentProperty::SUBTITLE_STREAM); + job->set_progress_unknown (); - Content::examine (job); + Content::examine (film, job); shared_ptr examiner (new FFmpegExaminer (shared_from_this (), job)); @@ -297,25 +307,35 @@ FFmpegContent::examine (shared_ptr job) AudioStreamPtr as = audio->streams().front(); AudioMapping m = as->mapping (); - film()->make_audio_mapping_default (m, first_path); + m.make_default (film ? film->audio_processor() : 0, first_path); as->set_mapping (m); } _subtitle_streams = examiner->subtitle_streams (); if (!_subtitle_streams.empty ()) { - caption.clear (); - caption.push_back (shared_ptr (new TextContent (this, CAPTION_OPEN))); + text.clear (); + text.push_back (shared_ptr (new TextContent (this, TEXT_OPEN_SUBTITLE, TEXT_UNKNOWN))); _subtitle_stream = _subtitle_streams.front (); } + _encrypted = first_path.extension() == ".ecinema"; } if (examiner->has_video ()) { set_default_colour_conversion (); } - signal_changed (FFmpegContentProperty::SUBTITLE_STREAMS); - signal_changed (FFmpegContentProperty::SUBTITLE_STREAM); + if (examiner->has_video() && examiner->pulldown() && video_frame_rate() && fabs(*video_frame_rate() - 29.97) < 0.001) { + /* FFmpeg has detected this file as 29.97 and the examiner thinks it is using "soft" 2:3 pulldown (telecine). + * This means we can treat it as a 23.976fps file. + */ + set_video_frame_rate (24000.0 / 1001); + video->set_length (video->length() * 24.0 / 30); + } + +#ifdef DCPOMATIC_VARIANT_SWAROOP + _id = examiner->id (); +#endif } string @@ -369,12 +389,12 @@ FFmpegContent::technical_summary () const void FFmpegContent::set_subtitle_stream (shared_ptr s) { + ChangeSignaller cc (this, FFmpegContentProperty::SUBTITLE_STREAM); + { boost::mutex::scoped_lock lm (_mutex); _subtitle_stream = s; } - - signal_changed (FFmpegContentProperty::SUBTITLE_STREAM); } bool @@ -390,32 +410,52 @@ operator!= (FFmpegStream const & a, FFmpegStream const & b) } DCPTime -FFmpegContent::full_length () const +FFmpegContent::full_length (shared_ptr film) const +{ + FrameRateChange const frc (film, shared_from_this()); + if (video) { + return DCPTime::from_frames (llrint (video->length_after_3d_combine() * frc.factor()), film->video_frame_rate()); + } + + if (audio) { + DCPTime longest; + BOOST_FOREACH (AudioStreamPtr i, audio->streams()) { + longest = max (longest, DCPTime::from_frames(llrint(i->length() / frc.speed_up), i->frame_rate())); + } + return longest; + } + + /* XXX: subtitle content? */ + + return DCPTime(); +} + +DCPTime +FFmpegContent::approximate_length () const { - FrameRateChange const frc (active_video_frame_rate (), film()->video_frame_rate ()); if (video) { - return DCPTime::from_frames (llrint (video->length_after_3d_combine() * frc.factor()), film()->video_frame_rate()); + return DCPTime::from_frames (video->length_after_3d_combine(), 24); } DCPOMATIC_ASSERT (audio); - DCPTime longest; + Frame longest = 0; BOOST_FOREACH (AudioStreamPtr i, audio->streams ()) { - longest = max (longest, DCPTime::from_frames (llrint (i->length() / frc.speed_up), i->frame_rate())); + longest = max (longest, Frame(llrint(i->length()))); } - return longest; + return DCPTime::from_frames (longest, 24); } void FFmpegContent::set_filters (vector const & filters) { + ChangeSignaller cc (this, FFmpegContentProperty::FILTERS); + { boost::mutex::scoped_lock lm (_mutex); _filters = filters; } - - signal_changed (FFmpegContentProperty::FILTERS); } string @@ -427,8 +467,8 @@ FFmpegContent::identifier () const s += "_" + video->identifier(); } - if (only_caption() && only_caption()->use() && only_caption()->burn()) { - s += "_" + only_caption()->identifier(); + if (only_text() && only_text()->use() && only_text()->burn()) { + s += "_" + only_text()->identifier(); } boost::mutex::scoped_lock lm (_mutex); @@ -480,9 +520,9 @@ FFmpegContent::set_default_colour_conversion () } void -FFmpegContent::add_properties (list& p) const +FFmpegContent::add_properties (shared_ptr film, list& p) const { - Content::add_properties (p); + Content::add_properties (film, p); if (video) { video->add_properties (p); @@ -617,7 +657,7 @@ FFmpegContent::add_properties (list& p) const } if (audio) { - audio->add_properties (p); + audio->add_properties (film, p); } } @@ -629,7 +669,8 @@ FFmpegContent::add_properties (list& p) const void FFmpegContent::signal_subtitle_stream_changed () { - signal_changed (FFmpegContentProperty::SUBTITLE_STREAM); + /* XXX: this is too late; really it should be before the change */ + ChangeSignaller cc (this, FFmpegContentProperty::SUBTITLE_STREAM); } vector >