/*
- Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include "filter.h"
#include "film.h"
#include "log.h"
+#include "config.h"
#include "exceptions.h"
#include "frame_rate_change.h"
#include "text_content.h"
#include <libavutil/pixdesc.h>
}
#include <libxml++/libxml++.h>
-#include <boost/foreach.hpp>
#include <iostream>
#include "i18n.h"
-#define LOG_GENERAL(...) dcpomatic_log->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL);
-
using std::string;
using std::vector;
using std::list;
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 (boost::filesystem::path p)
: Content (p)
- , _encrypted (false)
{
}
_color_trc = get_optional_enum<AVColorTransferCharacteristic>(node, "ColorTransferCharacteristic");
_colorspace = get_optional_enum<AVColorSpace>(node, "Colorspace");
_bits_per_pixel = node->optional_number_child<int> ("BitsPerPixel");
- _decryption_key = node->optional_string_child ("DecryptionKey");
- _encrypted = node->optional_bool_child("Encrypted").get_value_or(false);
}
FFmpegContent::FFmpegContent (vector<shared_ptr<Content> > c)
_color_trc = ref->_color_trc;
_colorspace = ref->_colorspace;
_bits_per_pixel = ref->_bits_per_pixel;
- _encrypted = ref->_encrypted;
}
void
if (audio) {
audio->as_xml (node);
- BOOST_FOREACH (AudioStreamPtr i, audio->streams ()) {
+ for (auto i: audio->streams ()) {
shared_ptr<FFmpegAudioStream> f = dynamic_pointer_cast<FFmpegAudioStream> (i);
DCPOMATIC_ASSERT (f);
f->as_xml (node->add_child("AudioStream"));
if (_bits_per_pixel) {
node->add_child("BitsPerPixel")->add_child_text (raw_convert<string> (*_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
ChangeSignaller<Content> cc1 (this, FFmpegContentProperty::SUBTITLE_STREAMS);
ChangeSignaller<Content> cc2 (this, FFmpegContentProperty::SUBTITLE_STREAM);
- job->set_progress_unknown ();
+ if (job) {
+ job->set_progress_unknown ();
+ }
Content::examine (film, job);
if (!examiner->audio_streams().empty ()) {
audio.reset (new AudioContent (this));
- BOOST_FOREACH (shared_ptr<FFmpegAudioStream> i, examiner->audio_streams ()) {
+ for (auto i: examiner->audio_streams ()) {
audio->add_stream (i);
}
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);
}
text.push_back (shared_ptr<TextContent> (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 ();
}
+
+ 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
FFmpegContent::technical_summary () const
{
string as = "";
- BOOST_FOREACH (shared_ptr<FFmpegAudioStream> i, ffmpeg_audio_streams ()) {
+ for (auto i: ffmpeg_audio_streams ()) {
as += i->technical_summary () + " " ;
}
DCPTime
FFmpegContent::full_length (shared_ptr<const Film> film) const
{
- FrameRateChange const frc (active_video_frame_rate(film), film->video_frame_rate());
+ 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;
+ for (auto 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
+{
+ if (video) {
+ return DCPTime::from_frames (video->length_after_3d_combine(), 24);
+ }
+
DCPOMATIC_ASSERT (audio);
- DCPTime longest;
- BOOST_FOREACH (AudioStreamPtr i, audio->streams ()) {
- longest = max (longest, DCPTime::from_frames (llrint (i->length() / frc.speed_up), i->frame_rate()));
+ Frame longest = 0;
+ for (auto i: audio->streams()) {
+ longest = max (longest, Frame(llrint(i->length())));
}
- return longest;
+ return DCPTime::from_frames (longest, 24);
}
void
void
FFmpegContent::add_properties (shared_ptr<const Film> film, list<UserProperty>& 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:
/// 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;
vector<shared_ptr<FFmpegAudioStream> > fa;
if (audio) {
- BOOST_FOREACH (AudioStreamPtr i, audio->streams()) {
+ for (auto i: audio->streams()) {
fa.push_back (dynamic_pointer_cast<FFmpegAudioStream> (i));
}
}
Content::take_settings_from (c);
_filters = fc->_filters;
}
+