X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_content.cc;h=a8b7fb716cecf92d39b1b931ddf7d49277f35bee;hb=6f344b876689a1234a5eb75041882f06f5d9fe5c;hp=2c2d36a986c6eb3b725b40c9222e38d5f9e043d6;hpb=aeb835a18c8df347e0ed68fb24631b320abeb611;p=dcpomatic.git diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 2c2d36a98..a8b7fb716 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2015 Carl Hetherington + Copyright (C) 2013-2016 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,6 +18,7 @@ */ #include "ffmpeg_content.h" +#include "video_content.h" #include "ffmpeg_examiner.h" #include "ffmpeg_subtitle_stream.h" #include "ffmpeg_audio_stream.h" @@ -60,22 +61,24 @@ int const FFmpegContentProperty::FILTERS = 102; FFmpegContent::FFmpegContent (shared_ptr film, boost::filesystem::path p) : Content (film, p) - , VideoContent (film, p) , AudioContent (film, p) , SubtitleContent (film, p) { + video.reset (new VideoContent (this, film)); + set_default_colour_conversion (); } FFmpegContent::FFmpegContent (shared_ptr film, cxml::ConstNodePtr node, int version, list& notes) : Content (film, node) - , VideoContent (film, node, version) , AudioContent (film, node) , SubtitleContent (film, node, version) { + video.reset (new VideoContent (this, film, node, version)); + list c = node->node_children ("SubtitleStream"); for (list::const_iterator i = c.begin(); i != c.end(); ++i) { - _subtitle_streams.push_back (shared_ptr (new FFmpegSubtitleStream (*i))); + _subtitle_streams.push_back (shared_ptr (new FFmpegSubtitleStream (*i, version))); if ((*i)->optional_number_child ("Selected")) { _subtitle_stream = _subtitle_streams.back (); } @@ -117,10 +120,11 @@ FFmpegContent::FFmpegContent (shared_ptr film, cxml::ConstNodePtr no FFmpegContent::FFmpegContent (shared_ptr film, vector > c) : Content (film, c) - , VideoContent (film, c) , AudioContent (film, c) , SubtitleContent (film, c) { + video.reset (new VideoContent (this, film, c)); + shared_ptr ref = dynamic_pointer_cast (c[0]); DCPOMATIC_ASSERT (ref); @@ -131,10 +135,18 @@ FFmpegContent::FFmpegContent (shared_ptr film, vectorsubtitle_streams (); _subtitle_stream = ref->subtitle_stream (); _audio_streams = ref->ffmpeg_audio_streams (); _first_video = ref->_first_video; + _filters = ref->_filters; + _color_range = ref->_color_range; + _color_primaries = ref->_color_primaries; + _color_trc = ref->_color_trc; + _colorspace = ref->_colorspace; + _bits_per_pixel = ref->_bits_per_pixel; } void @@ -142,7 +154,7 @@ FFmpegContent::as_xml (xmlpp::Node* node) const { node->add_child("Type")->add_child_text ("FFmpeg"); Content::as_xml (node); - VideoContent::as_xml (node); + video->as_xml (node); AudioContent::as_xml (node); SubtitleContent::as_xml (node); @@ -185,10 +197,8 @@ FFmpegContent::examine (shared_ptr job) Content::examine (job); shared_ptr examiner (new FFmpegExaminer (shared_from_this (), job)); - take_from_video_examiner (examiner); - - shared_ptr film = _film.lock (); - DCPOMATIC_ASSERT (film); + video->take_from_video_examiner (examiner); + set_default_colour_conversion (); { boost::mutex::scoped_lock lm (_mutex); @@ -202,7 +212,7 @@ FFmpegContent::examine (shared_ptr job) if (!_audio_streams.empty ()) { AudioMapping m = _audio_streams.front()->mapping (); - film->make_audio_mapping_default (m); + film()->make_audio_mapping_default (m); _audio_streams.front()->set_mapping (m); } @@ -247,7 +257,7 @@ FFmpegContent::technical_summary () const string filt = Filter::ffmpeg_string (_filters); return Content::technical_summary() + " - " - + VideoContent::technical_summary() + " - " + + video->technical_summary() + " - " + AudioContent::technical_summary() + " - " + String::compose ( "ffmpeg: audio %1 subtitle %2 filters %3", as, ss, filt @@ -280,10 +290,8 @@ operator!= (FFmpegStream const & a, FFmpegStream const & b) DCPTime FFmpegContent::full_length () const { - shared_ptr film = _film.lock (); - DCPOMATIC_ASSERT (film); - FrameRateChange const frc (video_frame_rate (), film->video_frame_rate ()); - return DCPTime::from_frames (llrint (video_length_after_3d_combine() * frc.factor()), film->video_frame_rate()); + FrameRateChange const frc (video->video_frame_rate (), film()->video_frame_rate ()); + return DCPTime::from_frames (llrint (video->video_length_after_3d_combine() * frc.factor()), film()->video_frame_rate()); } void @@ -302,7 +310,8 @@ FFmpegContent::identifier () const { SafeStringStream s; - s << VideoContent::identifier() << "_" + s << Content::identifier() << "_" + << video->identifier() << "_" << SubtitleContent::identifier(); boost::mutex::scoped_lock lm (_mutex); @@ -319,39 +328,62 @@ FFmpegContent::identifier () const } list -FFmpegContent::subtitles_during (ContentTimePeriod period, bool starting) const +FFmpegContent::image_subtitles_during (ContentTimePeriod period, bool starting) const +{ + shared_ptr stream = subtitle_stream (); + if (!stream) { + return list (); + } + + return stream->image_subtitles_during (period, starting); +} + +list +FFmpegContent::text_subtitles_during (ContentTimePeriod period, bool starting) const { shared_ptr stream = subtitle_stream (); if (!stream) { return list (); } - return stream->subtitles_during (period, starting); + return stream->text_subtitles_during (period, starting); } bool -FFmpegContent::has_text_subtitles () const +FFmpegContent::has_image_subtitles () const { + BOOST_FOREACH (shared_ptr i, subtitle_streams()) { + if (i->has_image_subtitles()) { + return true; + } + } + return false; } bool -FFmpegContent::has_image_subtitles () const +FFmpegContent::has_text_subtitles () const { - return !subtitle_streams().empty (); + BOOST_FOREACH (shared_ptr i, subtitle_streams()) { + if (i->has_text_subtitles()) { + return true; + } + } + + return false; } void FFmpegContent::set_default_colour_conversion () { - dcp::Size const s = video_size (); + dcp::Size const s = video->video_size (); boost::mutex::scoped_lock lm (_mutex); if (s.width < 1080) { - _colour_conversion = PresetColourConversion::from_id ("rec601").conversion; + video->set_colour_conversion (PresetColourConversion::from_id ("rec601").conversion); } else { - _colour_conversion = PresetColourConversion::from_id ("rec709").conversion; + video->set_colour_conversion (PresetColourConversion::from_id ("rec709").conversion); } } @@ -366,9 +398,11 @@ FFmpegContent::audio_streams () const } void -FFmpegContent::add_properties (list >& p) const +FFmpegContent::add_properties (list& p) const { - VideoContent::add_properties (p); + Content::add_properties (p); + video->add_properties (p); + AudioContent::add_properties (p); if (_bits_per_pixel) { int const sub = 219 * pow (2, _bits_per_pixel.get() - 8); @@ -376,13 +410,23 @@ FFmpegContent::add_properties (list >& p) const switch (_color_range) { case AVCOL_RANGE_UNSPECIFIED: - p.push_back (make_pair (_("Colour range"), _("Unspecified"))); + /// TRANSLATORS: this means that the range of pixel values used in this + /// file is unknown (not specified in the file). + p.push_back (UserProperty (_("Video"), _("Colour range"), _("Unspecified"))); break; case AVCOL_RANGE_MPEG: - p.push_back (make_pair (_("Colour range"), String::compose (_("Limited (%1-%2)"), (total - sub) / 2, (total + sub) / 2))); + /// TRANSLATORS: this means that the range of pixel values used in this + /// file is limited, so that not all possible values are valid. + p.push_back ( + UserProperty ( + _("Video"), _("Colour range"), String::compose (_("Limited (%1-%2)"), (total - sub) / 2, (total + sub) / 2) + ) + ); break; case AVCOL_RANGE_JPEG: - p.push_back (make_pair (_("Colour range"), String::compose (_("Full (0-%1)"), total))); + /// TRANSLATORS: this means that the range of pixel values used in this + /// file is full, so that all possible pixel values are valid. + p.push_back (UserProperty (_("Video"), _("Colour range"), String::compose (_("Full (0-%1)"), total))); break; default: DCPOMATIC_ASSERT (false); @@ -390,13 +434,19 @@ FFmpegContent::add_properties (list >& p) const } else { switch (_color_range) { case AVCOL_RANGE_UNSPECIFIED: - p.push_back (make_pair (_("Colour range"), _("Unspecified"))); + /// TRANSLATORS: this means that the range of pixel values used in this + /// file is unknown (not specified in the file). + p.push_back (UserProperty (_("Video"), _("Colour range"), _("Unspecified"))); break; case AVCOL_RANGE_MPEG: - p.push_back (make_pair (_("Colour range"), _("Limited"))); + /// TRANSLATORS: this means that the range of pixel values used in this + /// file is limited, so that not all possible values are valid. + p.push_back (UserProperty (_("Video"), _("Colour range"), _("Limited"))); break; case AVCOL_RANGE_JPEG: - p.push_back (make_pair (_("Colour range"), _("Full"))); + /// TRANSLATORS: this means that the range of pixel values used in this + /// file is full, so that all possible pixel values are valid. + p.push_back (UserProperty (_("Video"), _("Colour range"), _("Full"))); break; default: DCPOMATIC_ASSERT (false); @@ -413,11 +463,12 @@ FFmpegContent::add_properties (list >& p) const _("SMPTE 170M (BT601)"), _("SMPTE 240M"), _("Film"), - _("BT2020") + _("BT2020"), + _("SMPTE ST 428-1 (CIE 1931 XYZ)") }; - DCPOMATIC_ASSERT (AVCOL_PRI_NB == 10); - p.push_back (make_pair (_("Colour primaries"), primaries[_color_primaries])); + DCPOMATIC_ASSERT (AVCOL_PRI_NB == 11); + p.push_back (UserProperty (_("Video"), _("Colour primaries"), primaries[_color_primaries])); char const * transfers[] = { _("Unspecified"), @@ -435,11 +486,13 @@ FFmpegContent::add_properties (list >& p) const _("BT1361 extended colour gamut"), _("IEC61966-2-1 (sRGB or sYCC)"), _("BT2020 for a 10-bit system"), - _("BT2020 for a 12-bit system") + _("BT2020 for a 12-bit system"), + _("SMPTE ST 2084 for 10, 12, 14 and 16 bit systems"), + _("SMPTE ST 428-1") }; - DCPOMATIC_ASSERT (AVCOL_TRC_NB == 16); - p.push_back (make_pair (_("Colour transfer characteristic"), transfers[_color_trc])); + DCPOMATIC_ASSERT (AVCOL_TRC_NB == 18); + p.push_back (UserProperty (_("Video"), _("Colour transfer characteristic"), transfers[_color_trc])); char const * spaces[] = { _("RGB / sRGB (IEC61966-2-1)"), @@ -456,9 +509,26 @@ FFmpegContent::add_properties (list >& p) const }; DCPOMATIC_ASSERT (AVCOL_SPC_NB == 11); - p.push_back (make_pair (_("Colourspace"), spaces[_colorspace])); + p.push_back (UserProperty (_("Video"), _("Colourspace"), spaces[_colorspace])); if (_bits_per_pixel) { - p.push_back (make_pair (_("Bits per pixel"), raw_convert (_bits_per_pixel.get ()))); + p.push_back (UserProperty (_("Video"), _("Bits per pixel"), raw_convert (_bits_per_pixel.get ()))); } } + +/** Our subtitle streams have colour maps, which can be changed, but + * they have no way of signalling that change. As a hack, we have this + * method which callers can use when they've modified one of our subtitle + * streams. + */ +void +FFmpegContent::signal_subtitle_stream_changed () +{ + signal_changed (FFmpegContentProperty::SUBTITLE_STREAM); +} + +double +FFmpegContent::subtitle_video_frame_rate () const +{ + return video->video_frame_rate (); +}