X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_content.cc;h=6f3aceff8609da3cea061be3858edcd60ac9a3b2;hb=dd9be86db6cde0afa5da0d1d1ac43b42e05dca26;hp=961c0b0a39c77d9a63372f4fb34b870fa98fdc33;hpb=5dbd022f3abb0ebab57fb67073a07ed60df902a6;p=dcpomatic.git diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 961c0b0a3..6f3aceff8 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 Carl Hetherington + Copyright (C) 2013-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -30,6 +30,7 @@ #include "filter.h" #include "film.h" #include "log.h" +#include "config.h" #include "exceptions.h" #include "frame_rate_change.h" #include "text_content.h" @@ -45,8 +46,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; @@ -54,17 +53,19 @@ using std::cout; using std::pair; using std::make_pair; using std::max; -using boost::shared_ptr; -using boost::dynamic_pointer_cast; +using std::shared_ptr; +using std::dynamic_pointer_cast; using boost::optional; using dcp::raw_convert; +using namespace dcpomatic; int const FFmpegContentProperty::SUBTITLE_STREAMS = 100; int const FFmpegContentProperty::SUBTITLE_STREAM = 101; int const FFmpegContentProperty::FILTERS = 102; +int const FFmpegContentProperty::KDM = 103; -FFmpegContent::FFmpegContent (shared_ptr film, boost::filesystem::path p) - : Content (film, p) +FFmpegContent::FFmpegContent (boost::filesystem::path p) + : Content (p) { } @@ -80,8 +81,8 @@ 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); @@ -125,11 +126,10 @@ 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"); - } -FFmpegContent::FFmpegContent (shared_ptr film, vector > c) - : Content (film, c) +FFmpegContent::FFmpegContent (vector > c) + : Content (c) { vector >::const_iterator i = c.begin (); @@ -249,14 +249,16 @@ FFmpegContent::as_xml (xmlpp::Node* node, bool with_paths) const } 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 (); + if (job) { + job->set_progress_unknown (); + } - Content::examine (job); + Content::examine (film, job); shared_ptr examiner (new FFmpegExaminer (shared_from_this (), job)); @@ -300,7 +302,7 @@ 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); } @@ -310,12 +312,19 @@ FFmpegContent::examine (shared_ptr job) text.push_back (shared_ptr (new TextContent (this, TEXT_OPEN_SUBTITLE, TEXT_UNKNOWN))); _subtitle_stream = _subtitle_streams.front (); } - } if (examiner->has_video ()) { set_default_colour_conversion (); } + + 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); + } } string @@ -390,21 +399,41 @@ 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 @@ -480,16 +509,18 @@ 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); if (_bits_per_pixel) { - int const sub = 219 * pow (2, _bits_per_pixel.get() - 8); - int const total = pow (2, _bits_per_pixel.get()); + /* Assuming there's three components, so bits per pixel component is _bits_per_pixel / 3 */ + int const lim_start = pow(2, _bits_per_pixel.get() / 3 - 4); + int const lim_end = 235 * pow(2, _bits_per_pixel.get() / 3 - 8); + int const total = pow(2, _bits_per_pixel.get() / 3); switch (_color_range.get_value_or(AVCOL_RANGE_UNSPECIFIED)) { case AVCOL_RANGE_UNSPECIFIED: @@ -502,7 +533,7 @@ FFmpegContent::add_properties (list& p) const /// file is limited, so that not all possible values are valid. p.push_back ( UserProperty ( - UserProperty::VIDEO, _("Colour range"), String::compose (_("Limited (%1-%2)"), (total - sub) / 2, (total + sub) / 2) + UserProperty::VIDEO, _("Colour range"), String::compose(_("Limited (%1-%2)"), lim_start, lim_end) ) ); break; @@ -617,7 +648,7 @@ FFmpegContent::add_properties (list& p) const } if (audio) { - audio->add_properties (p); + audio->add_properties (film, p); } } @@ -658,3 +689,4 @@ FFmpegContent::take_settings_from (shared_ptr c) Content::take_settings_from (c); _filters = fc->_filters; } +