#include "log.h"
#include "exceptions.h"
#include "frame_rate_change.h"
-#include "safe_stringstream.h"
-#include "raw_convert.h"
#include "subtitle_content.h"
+#include <dcp/raw_convert.h>
#include <libcxml/cxml.h>
extern "C" {
#include <libavformat/avformat.h>
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
using boost::optional;
+using dcp::raw_convert;
int const FFmpegContentProperty::SUBTITLE_STREAMS = 100;
int const FFmpegContentProperty::SUBTITLE_STREAM = 101;
: Content (film, node)
{
video = VideoContent::from_xml (this, node, version);
- audio = AudioContent::from_xml (this, node);
+ audio = AudioContent::from_xml (this, node, version);
subtitle = SubtitleContent::from_xml (this, node, version);
list<cxml::NodePtr> c = node->node_children ("SubtitleStream");
}
-FFmpegContent::FFmpegContent (shared_ptr<const Film> film, vector<boost::shared_ptr<Content> > c)
+FFmpegContent::FFmpegContent (shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
: Content (film, c)
{
- video.reset (new VideoContent (this, c));
- audio.reset (new AudioContent (this, c));
- subtitle.reset (new SubtitleContent (this, c));
+ vector<shared_ptr<Content> >::const_iterator i = c.begin ();
+
+ bool need_video = false;
+ bool need_audio = false;
+ bool need_subtitle = false;
+
+ if (i != c.end ()) {
+ need_video = static_cast<bool> ((*i)->video);
+ need_audio = static_cast<bool> ((*i)->audio);
+ need_subtitle = static_cast<bool> ((*i)->subtitle);
+ }
+
+ while (i != c.end ()) {
+ if (need_video != static_cast<bool> ((*i)->video)) {
+ throw JoinError (_("Content to be joined must all have or not have video"));
+ }
+ if (need_audio != static_cast<bool> ((*i)->audio)) {
+ throw JoinError (_("Content to be joined must all have or not have audio"));
+ }
+ if (need_subtitle != static_cast<bool> ((*i)->subtitle)) {
+ throw JoinError (_("Content to be joined must all have or not have subtitles"));
+ }
+ ++i;
+ }
+
+ if (need_video) {
+ video.reset (new VideoContent (this, c));
+ }
+ if (need_audio) {
+ audio.reset (new AudioContent (this, c));
+ }
+ if (need_subtitle) {
+ subtitle.reset (new SubtitleContent (this, c));
+ }
shared_ptr<FFmpegContent> ref = dynamic_pointer_cast<FFmpegContent> (c[0]);
DCPOMATIC_ASSERT (ref);
for (size_t i = 0; i < c.size(); ++i) {
shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c[i]);
- if (fc->subtitle->use() && *(fc->_subtitle_stream.get()) != *(ref->_subtitle_stream.get())) {
+ if (fc->subtitle && fc->subtitle->use() && *(fc->_subtitle_stream.get()) != *(ref->_subtitle_stream.get())) {
throw JoinError (_("Content to be joined must use the same subtitle stream."));
}
}
}
void
-FFmpegContent::as_xml (xmlpp::Node* node) const
+FFmpegContent::as_xml (xmlpp::Node* node, bool with_paths) const
{
node->add_child("Type")->add_child_text ("FFmpeg");
- Content::as_xml (node);
+ Content::as_xml (node, with_paths);
if (video) {
video->as_xml (node);
node->add_child("FirstVideo")->add_child_text (raw_convert<string> (_first_video.get().get()));
}
- node->add_child("ColorRange")->add_child_text (raw_convert<string> (_color_range));
- node->add_child("ColorPrimaries")->add_child_text (raw_convert<string> (_color_primaries));
- node->add_child("ColorTransferCharacteristic")->add_child_text (raw_convert<string> (_color_trc));
- node->add_child("Colorspace")->add_child_text (raw_convert<string> (_colorspace));
+ node->add_child("ColorRange")->add_child_text (raw_convert<string> (static_cast<int> (_color_range)));
+ node->add_child("ColorPrimaries")->add_child_text (raw_convert<string> (static_cast<int> (_color_primaries)));
+ node->add_child("ColorTransferCharacteristic")->add_child_text (raw_convert<string> (static_cast<int> (_color_trc)));
+ node->add_child("Colorspace")->add_child_text (raw_convert<string> (static_cast<int> (_colorspace)));
if (_bits_per_pixel) {
node->add_child("BitsPerPixel")->add_child_text (raw_convert<string> (_bits_per_pixel.get ()));
}
if (examiner->has_video ()) {
video.reset (new VideoContent (this));
video->take_from_examiner (examiner);
- set_default_colour_conversion ();
}
+ boost::filesystem::path first_path = path (0);
+
{
boost::mutex::scoped_lock lm (_mutex);
AudioStreamPtr as = audio->streams().front();
AudioMapping m = as->mapping ();
- film()->make_audio_mapping_default (m);
+ film()->make_audio_mapping_default (m, first_path);
as->set_mapping (m);
}
}
+ if (examiner->has_video ()) {
+ set_default_colour_conversion ();
+ }
+
signal_changed (FFmpegContentProperty::SUBTITLE_STREAMS);
signal_changed (FFmpegContentProperty::SUBTITLE_STREAM);
}
string
FFmpegContent::identifier () const
{
- SafeStringStream s;
-
- s << Content::identifier();
+ string s = Content::identifier();
if (video) {
- s << "_" << video->identifier();
+ s += "_" + video->identifier();
}
if (subtitle) {
- s << "_" << subtitle->identifier();
+ s += "_" + subtitle->identifier();
}
boost::mutex::scoped_lock lm (_mutex);
if (_subtitle_stream) {
- s << "_" << _subtitle_stream->identifier ();
+ s += "_" + _subtitle_stream->identifier ();
}
for (vector<Filter const *>::const_iterator i = _filters.begin(); i != _filters.end(); ++i) {
- s << "_" << (*i)->id ();
+ s += "_" + (*i)->id ();
}
- return s.str ();
-}
-
-list<ContentTimePeriod>
-FFmpegContent::image_subtitles_during (ContentTimePeriod period, bool starting) const
-{
- shared_ptr<FFmpegSubtitleStream> stream = subtitle_stream ();
- if (!stream) {
- return list<ContentTimePeriod> ();
- }
-
- return stream->image_subtitles_during (period, starting);
-}
-
-list<ContentTimePeriod>
-FFmpegContent::text_subtitles_during (ContentTimePeriod period, bool starting) const
-{
- shared_ptr<FFmpegSubtitleStream> stream = subtitle_stream ();
- if (!stream) {
- return list<ContentTimePeriod> ();
- }
-
- return stream->text_subtitles_during (period, starting);
+ return s;
}
void
boost::mutex::scoped_lock lm (_mutex);
- if (s.width < 1080) {
- video->set_colour_conversion (PresetColourConversion::from_id ("rec601").conversion);
- } else {
+ switch (_colorspace) {
+ case AVCOL_SPC_RGB:
+ video->set_colour_conversion (PresetColourConversion::from_id ("srgb").conversion);
+ break;
+ case AVCOL_SPC_BT709:
video->set_colour_conversion (PresetColourConversion::from_id ("rec709").conversion);
+ break;
+ case AVCOL_SPC_BT470BG:
+ case AVCOL_SPC_SMPTE170M:
+ case AVCOL_SPC_SMPTE240M:
+ video->set_colour_conversion (PresetColourConversion::from_id ("rec601").conversion);
+ break;
+ case AVCOL_SPC_BT2020_CL:
+ case AVCOL_SPC_BT2020_NCL:
+ video->set_colour_conversion (PresetColourConversion::from_id ("rec2020").conversion);
+ break;
+ default:
+ if (s.width < 1080) {
+ video->set_colour_conversion (PresetColourConversion::from_id ("rec601").conversion);
+ } else {
+ video->set_colour_conversion (PresetColourConversion::from_id ("rec709").conversion);
+ }
+ break;
}
}
case AVCOL_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")));
+ p.push_back (UserProperty (UserProperty::VIDEO, _("Colour range"), _("Unspecified")));
break;
case AVCOL_RANGE_MPEG:
/// 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)
+ UserProperty::VIDEO, _("Colour range"), String::compose (_("Limited (%1-%2)"), (total - sub) / 2, (total + sub) / 2)
)
);
break;
case AVCOL_RANGE_JPEG:
/// 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)));
+ p.push_back (UserProperty (UserProperty::VIDEO, _("Colour range"), String::compose (_("Full (0-%1)"), total)));
break;
default:
DCPOMATIC_ASSERT (false);
case AVCOL_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")));
+ p.push_back (UserProperty (UserProperty::VIDEO, _("Colour range"), _("Unspecified")));
break;
case AVCOL_RANGE_MPEG:
/// 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")));
+ p.push_back (UserProperty (UserProperty::VIDEO, _("Colour range"), _("Limited")));
break;
case AVCOL_RANGE_JPEG:
/// 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")));
+ p.push_back (UserProperty (UserProperty::VIDEO, _("Colour range"), _("Full")));
break;
default:
DCPOMATIC_ASSERT (false);
_("SMPTE 240M"),
_("Film"),
_("BT2020"),
- _("SMPTE ST 428-1 (CIE 1931 XYZ)")
+ _("SMPTE ST 428-1 (CIE 1931 XYZ)"),
+ _("SMPTE ST 431-2 (2011)"),
+ _("SMPTE ST 432-1 D65 (2010)")
};
- DCPOMATIC_ASSERT (AVCOL_PRI_NB <= 11);
- p.push_back (UserProperty (_("Video"), _("Colour primaries"), primaries[_color_primaries]));
+ DCPOMATIC_ASSERT (AVCOL_PRI_NB <= 13);
+ p.push_back (UserProperty (UserProperty::VIDEO, _("Colour primaries"), primaries[_color_primaries]));
char const * transfers[] = {
_("Unspecified"),
_("BT2020 for a 10-bit system"),
_("BT2020 for a 12-bit system"),
_("SMPTE ST 2084 for 10, 12, 14 and 16 bit systems"),
- _("SMPTE ST 428-1")
+ _("SMPTE ST 428-1"),
+ _("ARIB STD-B67 ('Hybrid log-gamma')")
};
- DCPOMATIC_ASSERT (AVCOL_TRC_NB <= 18);
- p.push_back (UserProperty (_("Video"), _("Colour transfer characteristic"), transfers[_color_trc]));
+ DCPOMATIC_ASSERT (AVCOL_TRC_NB <= 19);
+ p.push_back (UserProperty (UserProperty::VIDEO, _("Colour transfer characteristic"), transfers[_color_trc]));
char const * spaces[] = {
_("RGB / sRGB (IEC61966-2-1)"),
_("YCOCG"),
_("BT2020 non-constant luminance"),
_("BT2020 constant luminance"),
+ _("SMPTE 2085, Y'D'zD'x"),
};
- DCPOMATIC_ASSERT (AVCOL_SPC_NB == 11);
- p.push_back (UserProperty (_("Video"), _("Colourspace"), spaces[_colorspace]));
+ DCPOMATIC_ASSERT (AVCOL_SPC_NB == 12);
+ p.push_back (UserProperty (UserProperty::VIDEO, _("Colourspace"), spaces[_colorspace]));
if (_bits_per_pixel) {
- p.push_back (UserProperty (_("Video"), _("Bits per pixel"), raw_convert<string> (_bits_per_pixel.get ())));
+ p.push_back (UserProperty (UserProperty::VIDEO, _("Bits per pixel"), _bits_per_pixel.get ()));
}
}
return fa;
}
+
+void
+FFmpegContent::use_template (shared_ptr<const Content> c)
+{
+ Content::use_template (c);
+
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (c);
+ _filters = fc->_filters;
+}